想象一下我们有界面
interface Foo {
bar: number | undefined;
}
Run Code Online (Sandbox Code Playgroud)
如果我们尝试创建Foo类型的对象,例如
const foo: Foo = {};
Run Code Online (Sandbox Code Playgroud)
由于缺少属性栏,因此无法编译。但是我们说它可以是未定义的,如果我们将它显式设置为undefined,它将起作用,但是,如果我们根本不将其设置为完全相同。它不应该与以下内容完全相同吗?
interface Foo {
bar?: number;
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这是一个问题,因为如果考虑更复杂的示例,则我们具有与字段的接口,该字段可以通过泛型类型选择。像这样,如果未指定泛型类型,则字段应该是未定义的;如果已指定,则字段只能是该类型的。例如
interface Foo<T = undefined> {
bar: T;
title: string;
}
const foo1: Foo = {
title: 'TITLE'
};
const foo2: Foo<number> = {
title: 'title',
bar: 12
};
Run Code Online (Sandbox Code Playgroud)
foo1会因为缺少属性而无法编译,但是无论如何它都必须是未定义的,如果我们明确指定它,它将可以工作,但这是完全相同的。我最终通过继承解决了这个问题,在继承中基类没有任何泛型参数,而子代已对其进行了严格指定。但是我只是好奇是否有人知道用这种方式处理未定义类型的具体原因。因为我自己找不到任何信息。
原因很简单,似乎还没有人实施它。当前类型检查器的实现方式最终要求需要 type 的属性undefined,但是有人提议以更有意义的方式改变行为,但还没有人得到它。
使用条件类型可以实现保持类型名称相同并使字段可选的解决方法:
type Foo<T = undefined> = {
title: string;
} & (T extends undefined ? {} : { bar: T});
const foo1: Foo = {
title: 'TITLE'
};
const foo2: Foo<number> = {
title: 'title',
bar:10
};
Run Code Online (Sandbox Code Playgroud)
这两种类型的签名并不完全相同(尽管它们足够接近,乍一看可能看不出区别)!
bar?: number表示对象可能没有名为的字段bar。bar: number | undefined表示该对象将始终具有一个称为的字段bar,但是该字段的值可能设置为undefined。在某些情况下,这种差异可能很重要,因为某些运行时行为取决于存在的字段与设置为未定义的字段之间的差异-请考虑是否调用Object.keys了该对象:
Object.keys({ bar: undefined }) // returns ["bar"]
Object.keys({}) // returns []
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1686 次 |
| 最近记录: |