是否有办法针对内置于该语言的联合类型对对象执行“instanceof”式查询?
我有一个带有联合类型的类型别名,如下所示:
type MyType = Foo | Bar | Thing;
Foo
,Bar
和Thing
中的每一个都继承自Base
class Base { /* ... */ }
class Foo extends Base { /* ... */ }
class Bar extends Base { /* ... */ }
class Thing extends Base { /* ... */ }
某些方法会返回Base
。
function getBase(): Base { /* ... */ return base; }
理想情况下,我想创建另一种方法,可以在调用MyType
后返回getBase()
function getMyType(): MyType {
var item = getBase();
if (item instanceof MyType)
return item;
else
return null;
}
如果MyType
不是类型别名,则上述代码可以正常工作。但是,由于它是一个类型别名,它似乎不起作用。那么为了重新思考我的问题,这种语言内置了这种语言吗?
显然,我想要的是通过针对每个单独的类检查instanceof查询来实现:
function getMyType(): MyType {
var item = getBase();
if (item instanceof Foo || item instanceof Bar || item instanceof Thing)
return item;
else
return null;
}
但这并不理想;如果某个未来的开发人员想要创建OtherThing
并扩展MyType
以包含此新类,那么希望记住更新getMyType()
。
语言中是否有内置功能可以解决此问题,还是有更好的方法可以做到这一点?
答案 0 :(得分:3)
没有类型别名的运行时表示,所以没有"内置"本身做这种检查本身。
但这种模式可以相当容易维护:
// Future devs: Please keep these in sync
type MyType = Foo|Bar|Thing;
let MyTypeClasses = [Foo,Bar,Thing];
function getMyType(): MyType {
var item = getBase();
if (MyTypeClasses.some(c => item instanceof c))
return item;
else
return null;
}
答案 1 :(得分:0)
自从接受的答案发布以来,Typescript引入了一些新功能,使此操作变得更加容易。现在,从Typescript 3.8.3开始,我将在2020年做到这一点:
const myTypes = ['Foo', 'Bar', 'Thing'] as const;
type MyType = typeof myType[number]; // 'Foo' | 'Bar' | 'Thing'
// Return a typed MyType if string is valid (else throw).
function getMyType(maybeMyType: string): MyType {
const myType = myTypes.find((validType) => validType === maybeMyType);
if (myType) {
return myType;
}
throw new Error(`String "${maybeMyType}" is not of type MyType.`);
}
// Use it like this:
const definitelyMyType = getMyType('Foo');
或者,如果您更喜欢安全性较低但可读性更高的自定义类型防护样式,则可以这样操作:
// Define a custom type guard to validate & assert that maybeMyType is MyType.
function isMyType(maybeMyType: string): maybeMyType is MyType {
return maybeMyType in myTypes;
}
// Use it like this:
const maybeMyType = 'Foo';
if (isMyType(maybeMyType)) {
const definitelyMyType: MyType = maybeMyType;
}