[英]Typescript: adding aliases via `Object.defineProperty` to an array type
If I have an array for this sake ['test', 'test2', 'test3']
, I'm adding aliases to it using Object.defineProperty()
that are defined in a different array ['a', 'b', 'c']
.如果为此我有一个数组
['test', 'test2', 'test3']
,我将使用Object.defineProperty()
添加别名,这些别名在不同的数组['a', 'b', 'c']
。
Here is my current (shortened) example that does not allow me to access the defined property on the returned array.这是我当前的(缩短的)示例,它不允许我访问返回数组上的已定义属性。
How can I have typescript recognise that there are defined properties on this array that match the values of the array ['a', 'b', 'c']
?我怎样才能让打字稿识别出这个数组上定义的属性与数组
['a', 'b', 'c']
的值相匹配?
const aliasArr = ['a', 'b', 'c'];
const applyAliases = <Alias extends string[], Values extends any[]>(aliases: Alias) => (arr: Values) => {
const definition = [...arr];
aliases.forEach((key, i) =>
Object.defineProperty(definition, key, {
enumerable: false,
get(): Values[number] {
return this[i];
},
})
);
return definition as typeof arr & { [P in keyof Alias]: Values[number] };
};
const applied = applyAliases<typeof aliasArr, string[]>(aliasArr)(['test', 'test2', 'test3']);
const test = applied.a // Error, property 'a' does not exist on type string[]
You've already figured out that applying mapped type to array results in array, so您已经发现将映射类型应用于数组会产生数组,所以
{ [P in keyof Alias]: Values[number] }
should be { [P in Alias[number]]: Values[number] }
or Record<Alias[number], Values[number]>
. { [P in keyof Alias]: Values[number] }
应该是{ [P in Alias[number]]: Values[number] }
或Record<Alias[number], Values[number]>
。
The missing part is restricting Alias[number]
to desired keys instead of just string[]
.缺少的部分是将
Alias[number]
限制为所需的键,而不仅仅是string[]
。 This can be achieved by defining aliasArr
as readonly tuple:这可以通过将
aliasArr
定义为只读元组来实现:
const aliasArr = ['a', 'b', 'c'] as const; // aliasArr is of type readonly ["a", "b", "c"]
const applyAliases = <Alias extends ReadonlyArray<string>>(aliases: Alias) => <Values extends any[]>(arr: Values) => {
const definition = [...arr];
aliases.forEach((key, i) =>
Object.defineProperty(definition, key, {
enumerable: false,
get(): Values[number] {
return this[i];
},
})
);
return definition as Values & Record<Alias[number], Values[number]>;
};
const applied = applyAliases(aliasArr)(['test', 'test2', 'test3']);
const test = applied.a // now OK
applied.x // Property 'x' does not exist on type 'string[] & { a: string; b: string; c: string; }'
** Second generic parameter moved to inner function, so typescript will be able to infer it properly ** 第二个泛型参数移动到内部函数,因此打字稿将能够正确推断它
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.