Typescript 复杂的打字推断
我有一个密码:Typescript 复杂的打字推断,typescript,typescript2.0,Typescript,Typescript2.0,我有一个密码: interface Cat{ meow:boolean } interface Zoo{ bobtail:Cat, bengal:Cat, cheetoh:Cat } 然后,在代码中的某个地方: let cats:Zoo;// imagine it's set correctly somewhere for(const i in cats) if(cats.hasOwnProperty(i)){ const creature=cats[i];
interface Cat{ meow:boolean }
interface Zoo{ bobtail:Cat, bengal:Cat, cheetoh:Cat }
然后,在代码中的某个地方:
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
if(cats.hasOwnProperty(i)){
const creature=cats[i];
/// well, the "creature" is of type "any" here...
}
当然我可以在这里做
const-biote:Cat=cats[I]
,但是有没有可能让TS猜到它除了猫之外什么都不能做呢?我的意思是,因为我总是依赖类型推断,有时我可能不会注意到这样的事情。有没有一种方法可以使它更严格,或者对于这种情况有什么最佳实践?谢谢。Typescript不能保证所有属性都是Cat
类型。对象cats
可以具有比接口中定义的更多的属性,并且在编译时它们的类型未知。只有在运行时才能确定对象具有哪些属性及其类型
您有三个选项来断言类型Cat
:类型强制转换、类型保护和hashmap类型
类型转换
当您确定Cat
的所有属性都是Cat
类型时,您只需将结果转换为Cat
:
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
if(cats.hasOwnProperty(i)){
const creature=cats[i] as Cat;
///the "creature" is of type "Cat" now...
}
type Zoo = { [key: string]: Cat };
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
const creature=cats[i];
///the "creature" is of type "Cat"...
类型防护装置
如果您不确定Cat
的所有属性是否为Cat
类型,则可以使用类型保护。只考虑正确类型的值:
//Define type guard
function isCat(value: any): value is Cat {
return value.hasOwnProperty('meow');
}
//...
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
const creature=cats[i];
if (cats.hasOwnProperty(i) && isCat(creature)) {
///the "creature" is of type "Cat" within the block...
}
哈希映射类型
根据您的要求,您可以将Zoo
接口替换为hashmap类型,该类型允许任意数量的Cat
类型的条目(或属性,如果您希望这样调用它们):
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
if(cats.hasOwnProperty(i)){
const creature=cats[i] as Cat;
///the "creature" is of type "Cat" now...
}
type Zoo = { [key: string]: Cat };
let cats:Zoo;// imagine it's set correctly somewhere
for(const i in cats)
const creature=cats[i];
///the "creature" is of type "Cat"...
此解决方案的缺点是无法设置特定的属性名称,就像您在示例中对接口所做的那样。从TypeScript 2.2开始,不允许使用此语法:
但在许多情况下,这是没有问题的,在这个解决方案中,您不需要任何额外的步骤,如强制转换和类型保护,因为类型可以推断。这是不可能的。它可以是猫以外的其他东西。当您说
cats:Zoo
时,您是说cats
对象必须至少实现Zoo
。它可以实现其他接口并具有其他属性,这些属性可能不是Cat
s。这不是“至少”。TypeScript可以编写类似于let cats:Zoo
的东西的原因是let
允许以后初始化变量。如果在以后的某个时刻,您想将某个内容分配给cats
,则必须满足接口的要求。由于成员不是可选的,assignedment必须设置所有三个。做一些类似于cats={bobtail:{meow:true}}不允许使用代码>。@SebastianSebald:问题在于没有分配属性以满足接口。问题在于,对象可以提供其他不同类型的属性。当您没有在代码中创建对象时(例如,当您从JSON反序列化对象时),您根本不能保证接口会得到满足。@Sefe Yes。我只想纠正“至少”的说法。实际上,您可以在authors代码中看到这一点。Zoo
接口正在使用hasOwnProperty
,尽管他从未定义过它;)@SebastianSebald:正如我所说的,如果cats
来自JSON(或者any
的简单转换),那么Zoo
的一些属性实际上可能是未定义的(或者是不同类型的)。