我想构建一个需要存在某些属性的类型,以防存在另一个属性。
为此,我想到使用联合类型的交集。联合类型可以是某些属性及其要求的组合,也可以是空类型。
以下代码不起作用,因为尽管缺少
desc
属性,但它不会出错:
export type A = {
a: string;
desc: string;
};
export type B = {
b: string;
} & (A | {});
const v: B = {
b: "",
a: "123"
};
用
{}
替换 Record<string, never>
会导致错误,因为所有属性现在都是 never
类型。
export type A = {
a: string;
desc: string;
};
export type B = {
b: string;
} & (A | Record<string, never>);
const v: B = {
b: "",
a: "123"
};
有没有办法让这个概念发挥作用?或者也许有更好的方法?
您的方法在概念上是正确的 - 您想要
A
的并集和与 A 没有公共键的类型。
不幸的是,类似于
(A | {})
的东西不起作用 - TS 类型允许额外的属性。
TS 对对象文字进行了过多的属性检查,但它不起作用
{}
联合。
const foo: {} = {a: 1}
ts-eslint 甚至有一条禁止其使用的规则:
Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `Record<string, unknown>` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record<string, never>`
A | Record<string, never>
单独工作效果很好,但是,正如您所注意到的,它不能作为与 {b: string;}
相交的一部分 - 记录力 b
永远不会。
您可以使用以下类型来表达
A or sth having no keys of A
export type A = {
a: string;
desc: string;
};
type NoneOf<T> = {
[K in keyof T]?: never
}
export type B = {
b: string;
} & (A | NoneOf<A>);
const v: B = {
b: "",
a: "123"
};
有Exact Types #12936的相关请求 - 不幸的是多年来没有实施。