根据泛型类型中其值的类型来约束 Key
Posted
技术标签:
【中文标题】根据泛型类型中其值的类型来约束 Key【英文标题】:Constrain a Key based on the type of its value in a generic type 【发布时间】:2021-08-10 12:53:57 【问题描述】:我正在尝试编写一个泛型函数,其中泛型类型用于键入其参数。
这是这个参数的一部分:
type Configuration<T> =
masterdata: T[],
target: ????
我在输入 target
属性时遇到问题。我希望它是特定类(MtmFormComponent
,当前类)中的任何属性的名称,但限制属性的类型是T[]
。
我的目标是写:this[configuration.target] = configuration.masterdata;
。
我已经完成了一半。以下是我现在输入target
的方式:
type MtmFormComponentPropertyOfType<T, K extends keyof MtmFormComponent> = MtmFormComponent[K] extends T[] ? K : never;
type DropdownAutocompleteConfiguration<T, K extends keyof MtmFormComponent> =
masterdata: T[],
targetFilteredList: MtmFormComponentPropertyOfType<T, K>,
;
当声明 DropdownAutocompleteConfiguration
类型的对象时,一切都很好,我的 IDE 的自动完成正确地限制我只使用导致与 masterdata
的值相同类型的键。所以我的类型似乎被正确定义了。
我的问题是在我的通用函数中使用该对象时:
private setupDropdownAutocompleteBehaviour<T, K extends keyof MtmFormComponent>(configuration: DropdownAutocompleteConfiguration<T, K>): void
this[configuration.targetFilteredList] = configuration.masterdata;
// ...
这里,this[configuration.targetFilteredList]
表达式给出以下错误:
类型 'T[]' 不能分配给类型 'this[Currency[] extends T[] ? "filteredCurrencyList" : never] & this[PriceUnit[] extends T[] ? "filteredPriceUnits" : never] & this[Subscription[] extends T[] ? “订阅”:从不]'。 类型 'T[]' 不能分配给类型 'this[Currency[] extends T[] ? “filteredCurrencyList”:从不]'。 类型“T[]”不可分配给类型“Currency[]”。 类型“T”不能分配给类型“货币”。
据我了解,在函数内部,TypeScript 完全解析了this[configuration.targetFilteredList]
的类型,而不是依赖于它是T[]
的事实。从我的 IDE 的自动完成功能来看,我确信我不能为 target
设置值,这会导致类型与 masterdata
不兼容。
我不知道从那里做什么:/
感谢您的帮助:)
【问题讨论】:
【参考方案1】:在这种特殊情况下,您是否必须使您的函数在目标属性键上通用?
举个具体的例子,假设MtmFormComponent
是这样定义的
interface MtmFormComponent
foo: string[];
bar: string[];
baz: number[];
qux: string;
现在,我们需要一个类型,它可以为我们提供T
类型的所有属性名称,其中属性名称映射到U[]
的值。我们可以这样定义这种类型:
type ArrayValuedProps<T, U> = [K in keyof T]: (T[K] extends U[] ? K : never) [keyof T]
这样,我们得到
ArrayValuedProps<MtmFormComponent, string> = foo: "foo"; bar: "bar"; baz: never; qux: never [keyof MtmFormComponent]
= foo: "foo"; bar: "bar"; baz: never; qux: never ["foo" | "bar" | "baz" | "qux"]
= "foo" | "bar" | never
= "foo" | "bar"
同样,ArrayValuedProps<MtmFormComponent, number>
等价于类型"baz"
;
使用它,我们可以像这样定义您的Configuration<T>
类型:
type Configuration<T> =
masterdata: T[],
target: ArrayValuedProps<MtmFormComponent, T>
我们可以完全避免将目标键作为类型参数。
【讨论】:
以上是关于根据泛型类型中其值的类型来约束 Key的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin泛型总结 ★ ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 | 可变参数结合泛型 | out 协变 | in 逆变 | reified 检查泛型参数类型 )