TypeScript class 属性 查找方法类型推断
TypeScript class property lookup method type inference
我正在努力让类型推断与 class 属性 查找一起使用。
我想要的:
class Family <T extends { [name: string]: Animal }> {
public members: T
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
const cat = new Cat
const dog = new Dog
const foo = new Family
foo.members = { kitty: cat, bob: dog }
const result1 = foo.lookup('missing') // I want this to fail for missing key. It doesn't.
const result2 = foo.lookup('kitty') // I want this has inferred type Cat. It doesn't.
我相信以上是可以实现的,因为我得到的功能版本如下所示
function lookup <O, K extends keyof O> (obj: O, key: K): O[K] {
return obj[key]
}
const o = { a:1, b: 'text'}
const r = lookup(o, 'a') // correctly inferred type number
const r2 = lookup(o, 'b') // correctly inferred type string
任何帮助或指南将不胜感激。提前致谢。
变量的类型一般是在声明变量的时候推断出来的,之后一般不会改变(所以foo
的类型为Family<{ [name: string]: Animal; >
因为在初始化的时候没有其他的可用信息)
如果您可以将 member
传递给构造函数,根据将按预期工作的参数推断 T
:
class Family <T extends { [name: string]: Animal }> {
constructor(public members: T) { }
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat
向构造函数显式指定类型参数也是一种选择,但不那么方便:
const foo = new Family<{ kitty: Cat, bob: Dog }>()
foo.members = { kitty: cat, bob: dog }
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat
现在,如果这些选项都不可行,您可以走更深奥的路线,并使用 custom assertion function。这些自定义断言如果用作顶级语句可以更改变量的类型:
class Family <T extends { [name: string]: Animal }> {
private members!: T;
public setMemebers<TNew extends T>(members: TNew): asserts this is Family<TNew> {
this.members = members;
}
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
const cat = new Cat
const dog = new Dog
const foo: Family<any> = new Family()
foo.setMemebers({ kitty: cat, bob: dog });
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat
我正在努力让类型推断与 class 属性 查找一起使用。
我想要的:
class Family <T extends { [name: string]: Animal }> {
public members: T
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
const cat = new Cat
const dog = new Dog
const foo = new Family
foo.members = { kitty: cat, bob: dog }
const result1 = foo.lookup('missing') // I want this to fail for missing key. It doesn't.
const result2 = foo.lookup('kitty') // I want this has inferred type Cat. It doesn't.
我相信以上是可以实现的,因为我得到的功能版本如下所示
function lookup <O, K extends keyof O> (obj: O, key: K): O[K] {
return obj[key]
}
const o = { a:1, b: 'text'}
const r = lookup(o, 'a') // correctly inferred type number
const r2 = lookup(o, 'b') // correctly inferred type string
任何帮助或指南将不胜感激。提前致谢。
变量的类型一般是在声明变量的时候推断出来的,之后一般不会改变(所以foo
的类型为Family<{ [name: string]: Animal; >
因为在初始化的时候没有其他的可用信息)
如果您可以将 member
传递给构造函数,根据将按预期工作的参数推断 T
:
class Family <T extends { [name: string]: Animal }> {
constructor(public members: T) { }
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat
向构造函数显式指定类型参数也是一种选择,但不那么方便:
const foo = new Family<{ kitty: Cat, bob: Dog }>()
foo.members = { kitty: cat, bob: dog }
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat
现在,如果这些选项都不可行,您可以走更深奥的路线,并使用 custom assertion function。这些自定义断言如果用作顶级语句可以更改变量的类型:
class Family <T extends { [name: string]: Animal }> {
private members!: T;
public setMemebers<TNew extends T>(members: TNew): asserts this is Family<TNew> {
this.members = members;
}
public lookup <K extends keyof T>(name: K): T[K] {
return this.members[name]
}
}
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
const cat = new Cat
const dog = new Dog
const foo: Family<any> = new Family()
foo.setMemebers({ kitty: cat, bob: dog });
const result1 = foo.lookup('missing') // err
const result2 = foo.lookup('kitty') // cat