我想写这样的东西:
const structs: Record<T extends StructureConstant,Array<ConcreteStructure<T>>> = Object.create(null);
其中StructureConstant
是常数的并集,ConcreteStructure
基本上是类型查找。
这在TypeScript中可能吗?我不知道如何使值依赖于密钥。
这里有一个完整的例子:
type StructureConstant = "road" | "tower";
interface Road {
a: "i am a road",
}
interface Tower {
b: "i be towerin"
}
type ConcreteStructure<T extends StructureConstant> = T extends "road"
? Road
: T extends "tower"
? Tower
: never;
type StuctureRecord<T extends StructureConstant> = Record<T, Array<ConcreteStructure<T>>>
const structs: StuctureRecord<StructureConstant> = Object.create(null);
const roads = structs["road"]; // should be Array<Road>|undefined
console.log(roads[0].a); // should work (if structs was populated)
TS游乐场
在typescript中,只有函数值可以具有泛型类型。其他值需要完全指定。
所以也许你想要这样的东西:
type StuctureRecord<T extends StructureConstant> = Record<T, Array<ConcreteStructure<T>>>
// structs doesn't have a generic type.
const structs: StuctureRecord<StructureConstant> = Object.create(null);
或
// function can have generic type.
const structsCreator = <T extends StructureConstant>(): Record<T, Array<ConcreteStructure<T>>> => Object.create(null)
const structs = structsCreator<StructureConstant>()
游乐场
要获得所描述的效果,您不能使用记录。记录将所有键映射到同一类型。如果每个条目需要不同的类型,则需要自定义映射类型
type StuctureMappedType<T extends StructureConstant> =
{ [K in T]: Array<ConcreteStructure<K>>}
游乐场
我最近遇到了一个非常类似的情况,诀窍是避免使用Record
实用程序:
type FilterValues<T> = T extends 'date'
? Date | null
: T extends 'date-range'
? [Date, Date] | [null, null]
: T extends 'select'
? string
: T extends 'text'
? string
: never
type FilterType = 'date-range' | 'select' | 'text'
type FilterRenderers = {
[K in FilterType]: (
value: FilterValues<K>,
setValue: (value: FilterValues<K>) => void,
) => ReactElement
}
const filterRenderers: FilterRenderers = {
'date-range': (value, setValue) => (
<FormattedDateRangePicker onChange={range => Array.isArray(range) && setValue(range)} />
),
select: () => null,
text: () => null,
}