简体   繁体   English

打字稿:通过`Object.defineProperty`向数组类型添加别名

[英]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; }'

Playground 操场


** Second generic parameter moved to inner function, so typescript will be able to infer it properly ** 第二个泛型参数移动到内部函数,因此打字稿将能够正确推断它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Object.defineProperty(Array.prototype .. TypeScript 中的问题 - Object.defineProperty(Array.prototype .. problem in TypeScript 如何在 Typescript 中为 getter 使用 Object.defineProperty? - How to use Object.defineProperty for getters in Typescript? TypeScript 键入:Object.defineProperty function 参数 - TypeScript typing: Object.defineProperty function args TypeScript正在添加Object.defineProperty(exports,“__ myModule”,{value:true}); 抛出一个错误 - TypeScript is adding Object.defineProperty(exports, “__esModule”, { value: true }); throwing an error 使用Object.defineProperty后如何读取typescript中的属性? - How to read properties in typescript after using Object.defineProperty? 如何禁用TypeScript Object.defineProperty(exports,“ __esModule”,{value:true})? - How to disable TypeScript Object.defineProperty(exports, “__esModule”, { value: true })? Vue.js 反应性和 Object.defineProperty 与 TypeScript - Vue.js reactivity and Object.defineProperty with TypeScript 使用 Object.defineProperty 时,类型中缺少属性,但类型中需要属性 - Property is missing in type but required in type when using Object.defineProperty 使用Object.defineProperty动态创建的类型检查属性 - Type-checking properties created dynamically with Object.defineProperty RequireJS模块的TypeScript编译生成一行Object.defineProperty(exports,“__ myModule”,{value:true}); 如何摆脱它? - TypeScript compilation of RequireJS module generates line Object.defineProperty(exports, “__esModule”, { value: true }); How to get rid of it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM