我需要定义一个类型,以便只接受这样的对象:如果同一对象中的另一个属性定义了值,则可以用值定义该属性。
我为我的需求尝试了下面的类型定义,它是最接近我想要的。
type TypeA = {
width?: number;
height?: number;
position: string;
innerSize?: string;
} | {
width?: number;
height?: number;
position?: undefined;
}
接收该类型对象的函数需要检查属性position
是否已定义,然后才能使用innerSize
,这很酷。
但是,在创建这种类型的对象时,我遇到了意想不到的事情:
function test() {
const a: TypeA = {};
const b: TypeA = { width: 50, height: 75 };
const c: TypeA = { position: "5, 7" };
// Type '{ innerSize: string; }' is not assignable to type 'TypeA'.
// Property 'position' is missing in type '{ innerSize: string; }' but required in type '{ width?: number | undefined; height?: number | undefined; position: string; innerSize?: string | undefined; }'.
const d: TypeA = { innerSize: "400, 120" };
const e: TypeA = { width: 50, innerSize: "400, 120" }; // It compiles!
}
我不能创建变量d
,因为Typescript要求定义属性position
,但是,我可以通过定义属性width
来绕过这个限制......那么,什么会产生这样的结果呢?
2条答案
按热度按时间myzjeezk1#
此对象在技术上与TypeA兼容,因为它与联合的以下部分匹配:
它的宽度是一个数字,它省略了高度和位置,所以它匹配类型。它确实有一个多余的属性innerSize,但是typescript在检查兼容性时允许多余的属性。
尽管如此,这并不是一个完整的解释,因为通常typescript会在你创建对象的那一行检查多余的属性,所以它应该捕捉到这一点,它应该捕捉到,但它没有,因为这是一个已知的(而且长期存在的)bug:https://github.com/microsoft/TypeScript/issues/20863
ep6jt1vc2#
作为一种解决方案,对于某些形状中不能定义的属性,请使用
never
类型:Playground链接