如何使用名为 `keyof` 类型的 属性 创建对象字面量
How to create object literal with a property named as `keyof` type
我什至找不到合适的词来表达这个问题。这是我想要实现的简化代码。
class Test<T, TId extends keyof T> {
public create(id: T[TId]): T {
return {
[TId]: id, // Error here. I want to set property `TId` to value `id`,
} as T;
}
}
interface A {
id: number;
}
interface B {
fileName: string;
}
new Test<A, 'id'>().create(123); // Want to get { id: 123 }
new Test<B, 'fileName'>().create('file'); // Want to get { fileName: 'file' }
错误是:Conversion of type '{ [x: number]: T[TId]; }' to type 'T' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. 'T' could be instantiated with an arbitrary type which could be unrelated to '{ [x: number]: T[TId]; }'.ts(2352)
恐怕您尝试做的事情不可能纯粹在类型上实现。问题在这里:
new Test<A, 'id'>().create(123); // Want to get { id: 123 }
编译为 JavaScript:
new Test().create(123);
你可以看到这里不可能用右键return一个对象,因为你的类型参数('id')在编译代码中不存在。类型信息在运行时不存在。
要解决此问题,您需要更改该设计,并将 'id'
作为字符串参数传递给 create
或 Test()
。例如:
class Test<T extends object, TId extends keyof T = keyof T> {
constructor(private readonly key: TId) { }
public create(value: T[TId]): T {
return { [this.key]: value } as T;
}
}
interface A {
id: number;
}
interface B {
fileName: string;
}
new Test<A>('id').create(123); // Returns { id: 123 }
new Test<B>('fileName').create('file'); // Returns { fileName: 'file' }
通过自动推断 TId
进行编译,执行您想要的操作,并强制执行正确的键名和值(因此 filePath
作为键或为 fileName
传递一个数字 won '编译)。
我什至找不到合适的词来表达这个问题。这是我想要实现的简化代码。
class Test<T, TId extends keyof T> {
public create(id: T[TId]): T {
return {
[TId]: id, // Error here. I want to set property `TId` to value `id`,
} as T;
}
}
interface A {
id: number;
}
interface B {
fileName: string;
}
new Test<A, 'id'>().create(123); // Want to get { id: 123 }
new Test<B, 'fileName'>().create('file'); // Want to get { fileName: 'file' }
错误是:Conversion of type '{ [x: number]: T[TId]; }' to type 'T' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. 'T' could be instantiated with an arbitrary type which could be unrelated to '{ [x: number]: T[TId]; }'.ts(2352)
恐怕您尝试做的事情不可能纯粹在类型上实现。问题在这里:
new Test<A, 'id'>().create(123); // Want to get { id: 123 }
编译为 JavaScript:
new Test().create(123);
你可以看到这里不可能用右键return一个对象,因为你的类型参数('id')在编译代码中不存在。类型信息在运行时不存在。
要解决此问题,您需要更改该设计,并将 'id'
作为字符串参数传递给 create
或 Test()
。例如:
class Test<T extends object, TId extends keyof T = keyof T> {
constructor(private readonly key: TId) { }
public create(value: T[TId]): T {
return { [this.key]: value } as T;
}
}
interface A {
id: number;
}
interface B {
fileName: string;
}
new Test<A>('id').create(123); // Returns { id: 123 }
new Test<B>('fileName').create('file'); // Returns { fileName: 'file' }
通过自动推断 TId
进行编译,执行您想要的操作,并强制执行正确的键名和值(因此 filePath
作为键或为 fileName
传递一个数字 won '编译)。