我可以创建一个断言保护器,断言对象中存在特定属性(或具有特定类型)。
即
我有一个接口Foo
:
interface Foo {
bar: string;
baz: number;
buzz?: string;
}
现在,Foo
类型的对象将具有可选的属性buzz。我将如何编写断言存在嗡嗡声的函数:
即
const item: Foo = getFooFromSomewhere();
if (!hasBuzz(item)) return;
const str: string = item.buzz;
我将如何实施hasBuzz()
?遵循打字保护的原则:
function hasBuzz(item: Foo): item.buzz is string {
return typeof item.buzz === 'string'
}
这样的东西存在吗?
PS:我知道我可以做到:
const item = getFooFromSomewhere();
if (typeof item.buzz === 'string') return;
const str: string = item.buzz;
但是我的实际用例要求我有一个单独的函数来断言buzz
的存在。
答案 0 :(得分:2)
我不喜欢这里的现有答案,因为它们都是特定于检查const iconContactWay = () => {
let [text, component] = ['Contact by Phone Call', <Phone />];
if (preferredContactWay === 'Email') {
[text, component] = ['Contact by Email', <Email />];
} else if (preferredContactWay === 'SMS') {
[text, component] = ['Contact by SMS', <Sms />];
}
return <StyledTooltip title={text}>{component}</StyledTooltip>;
};
对象的,但是您可以定义一个{ key: { text: '...', component: </> }, ... }
类型保护程序来检查 any 对象看看它是否具有Foo
属性。
hasBuzz
通过使用通用的buzz
作为输入并返回interface Buzzable {
buzz: string;
}
function hasBuzz<T extends {buzz?: any}>(obj: T): obj is T & Buzzable {
return typeof obj.buzz === "string";
}
而不是仅仅返回T
,在与obj is T & Buzzable
等特定接口进行检查时,不会丢失任何信息。 obj is Buzzable
。
如果Foo
是hasBuzz
,则打字稿会知道hasBuzz(item: Foo)
的类型是true
。在这种情况下,与item
相同,因为Foo & Buzzable
具有可选的Required<Foo>
属性,但是您可以检查任何对象。 Foo
完全有效,应始终返回buzz
。
答案 1 :(得分:0)
引用属性时可以使用definite assignment assertions。
function hasBuzz(item: Foo): string {
return item.buzz!;
}
如果您想将对象视为在代码中肯定还有buzz
,则可以缩小类型:
interface DefinitelyBuzzed extends Foo {
buzz: string;
}
答案 2 :(得分:0)
警卫的目的是允许您在不确定类型是什么时缩小范围:
您的情况可能有效的方法是:
interface Foo {
bar: string;
baz: number;
buzz?: string;
}
function hasBuzz(item: Foo|Required<Foo>): item is Required<Foo> {
return typeof item.buzz === 'string'
}
const f : Foo = {
bar: 'a',
baz: 1,
buzz: 'x'
};
const str : string = f.buzz; // error
if (hasBuzz(f)) {
const str2 : string = f.buzz; // works
}
Required
是一个辅助类型,给定另一种类型将返回具有所有必需属性(自ts 2.8起可用)的该类型。这会将您的item
变量缩小为Required<Foo>
类型
答案 3 :(得分:0)
这应该有效:
function hasBuzz(item: Foo): item is Foo & Required<Pick<Foo, 'buzz'>> {
return !!item.buzz
}