我正试图编写一个通用类,该类传递一个键key
,对应于一组已知的构造接口之一的键,以后可以传递一个对象thing
和类型安全访问thing[key]
。这是我得到的:
interface AB {
a: string
b: number
}
interface BC {
b: number
c: Date
}
type ABC = AB | BC
class Getter<T extends ABC> {
key: keyof T;
constructor(key: keyof T) {
this.key = key;
}
get(thing: T): string {
const value = thing[this.key];
return value.toString();
}
}
const getter = new Getter<AB>('b');
操场上联系
在这里,我希望Typescript推断,因为T extends ABC
,T[keyof T]
=AB[keyof AB] | BC [keyof BC]
=string | number | date
。然而,它似乎被困在T[keyof T]
。即使在该行添加as AB[keyof AB] | BC[keyof BC]
也不能修复它,我需要as unknown as AB[keyof AB] | BC[keyof BC]
!没有那条线,有没有办法让它工作?
还有,我是否可以将key
的值作为类型参数化,而不是将thing
的类型参数化?
当T extends ABC
时,它可以有许多其他属性和类型。因此不能有.toString()
方法。
type G = {
a: string;
b: number;
hello: undefined;
};
const g = new Getter<G, keyof G>("hello");
g.get({
a: "a",
b: 1,
hello: undefined
}); // undefined does not have .toString() method
操场上联系
是否有任何方法可以将key的值参数化为类型而不是参数化事物的类型?
是的,没有比这更容易的了。
class Getter<Key extends string | symbol> {
key: Key;
constructor(key: Key) {
this.key = key;
}
get(thing: {[k in Key]: string | number | Date}): string {
const value = thing[this.key];
return value.toString();
}
}
<一口>(操场演示)一口>
这仅仅是打字脚本本质的限制。您需要检查成员,然后在运行时执行类型强制转换。希望这对你有帮助!
例如:
if (AnimalObject.Object.Keys().Includes('Name')) {
// We now know the generic type has a matching member
}
至于实现,我将创建一个'T'可以使用的接口列表,然后为每个接口创建一个成员数组,按照上面的逻辑,你可能会得到这样的结果:
// Store your valid types for checking
const ValidInterfacesSet: any[] = {Dog,Cat,car,Mammal};
//Look through members and confirm them...
GetAndCastType(typeToCheck: any) {
typeToCheckKeys: string = typeToCheck.Object.keys();
for (inter: any of ValidInterfacesSet) {
const interMemberNames: string[] = inter.object.keys();
if(array1.sort().join(',')=== array2.sort().join(',')) {
// Returning the casted type if the iter members contain the same as typeToCheckMembers
return typeToCheck as inter;
}
}
}