给出以下类型:
interface FullName {
fullName?: string
}
interface Name {
firstName: string
lastName: string
}
type Person = FullName | Name;
const p1: Person = {};
const p2: Person = { fullName: 'test' };
const p3: Person = { firstName: 'test' }; // Does not throw
const p4: Person = { badProp: true }; // Does throw, as badProp is not on FullName | Name;
Run Code Online (Sandbox Code Playgroud)
我希望p3
会导致编译器错误,但firstName
没有lastName
,但它没有 - 这是一个错误或预期?
此外,使FullName.fullName必需会导致p3
(和p1
)导致错误.
首先,你的界面FullName
只包含一个可选属性,基本上它使它匹配任何东西.然后当你用它做一个联合类型时,结果类型将与所有东西兼容.
但是,考虑声明和分配文字对象还有另外一个问题,那就是你只能声明已知属性:为什么我会收到错误"对象文字只能指定已知属性"?
所以你可以毫无问题地做到这一点:
var test = { otherStuff: 23 };
const p4: Person = test;
Run Code Online (Sandbox Code Playgroud)
但不是这个
const p4: Person = { otherStuff: 23 };
Run Code Online (Sandbox Code Playgroud)
在你的情况下firstName
是一个已知的属性FullName | Name
,所以一切都好.
正如@artem回答的discriminated unions
那样,除了常规的工会之外,在打字稿中有特殊的含义,需要特殊的结构假设.
从通常意义上讲,您问题中的类型不是受歧视的联合 - 您的联合成员没有称为discriminant 的通用、非可选文字属性。
因此,正如 @Alex 在他的回答中指出的那样,你的工会有点类似于
type Person = {
fullName?: string
firstName?: string
lastName?: string
}
Run Code Online (Sandbox Code Playgroud)
所以它可以初始化{ firstName: 'test' }
使用真正的可区分联合,您可以恢复检查非可选属性的逻辑,以及检查对象文字是否只能指定已知属性:
interface FullName {
kind: 'fullname';
fullName?: string
}
interface Name {
kind: 'name';
firstName: string
lastName: string
}
type Person = FullName | Name;
const p1: Person = {kind: 'fullname'}; // ok
const p2: Person = {kind: 'fullname', fullName: 'test' }; // ok
Run Code Online (Sandbox Code Playgroud)
检查非可选属性:
const p3: Person = {kind: 'name', firstName: 'test' };
Run Code Online (Sandbox Code Playgroud)
错误:
Type '{ kind: "name"; firstName: string; }' is not assignable to type 'Person'.
Type '{ kind: "name"; firstName: string; }' is not assignable to type 'Name'.
Property 'lastName' is missing in type '{ kind: "name"; firstName: string; }'.
Run Code Online (Sandbox Code Playgroud)
检查额外的属性:
const p5: Person = { kind: 'fullname', bar: 42 }
Run Code Online (Sandbox Code Playgroud)
错误:
Type '{ kind: "fullname"; bar: number; }' is not assignable to type 'Person'.
Object literal may only specify known properties, and 'bar' does not exist in type 'Person'.
Run Code Online (Sandbox Code Playgroud)
然而,正如 @JeffMercado 发现的那样,类型检查仍然有点不对劲:
const p6: Person = { kind: 'fullname', firstName: 42 }; // no error. why?
Run Code Online (Sandbox Code Playgroud)
我会考虑发布 typescript github 项目的问题。
归档时间: |
|
查看次数: |
864 次 |
最近记录: |