繁体   English   中英

TypeScript接口重载如何解决?

[英]How to reslove TypeScript Interface heavy load?

type ItemProps = {
  a: string;
  b?: boolean;
  c?: string; 
}

const arr: ItemProps[] = [
 {
   a: 'demo',
   b: true,
   c: 'test'
 },
 {
   a: 'demo2'
 }
];

如果 prop b存在,如何定义ItemProps 如果 prop b存在 prop c必须定义?

我要这个:

const arr: ItemProps[] = [
 {
   a: 'demo',
   b: true,
   c: 'test'
 },
 {
   a: 'demo2',
   b: true, // ERROR, because b exist,but c undefined
 }
];

使用联合类型:

type ItemProps = { a: string; } & ({} | { b: boolean;  c: string; });

有了这个 Typescript 已经缩小了带有类型保护的联合类型,例如:

let item: ItemProps = { a: "test", b: true };

if("b" in item) {
  type Narrowed = typeof item;
  console.log(item.c)
} else {
  type Narrowed = typeof item;
  console.log(item.c); // ERROR
}

然而,不幸的是,有时 Typescript 允许指定比实际类型更多的属性,当类型是联合类型时,似乎就是这种情况。 因此,尽管使用联合类型,打字更准确,但在创建新的 ItemProps 期间它不会帮助你。

为此,您将需要一个可区分的 union ,例如,如果将两个不同的字符串文字类型用于共享属性a

type ItemProps = { a: "without" } | { a: "with", b: boolean;  c: string; };

这样,在分配 object 文字时,联合将被区分为基于 a 的 object 类型之一,然后只能指定已知属性:

type ItemProps = { a: "without" } | { a: "with", b: boolean;  c: string; };

const arr: ItemProps[] = [
 {
   a: 'with',
   b: true,
   c: 'test'
 },
 {
   a: 'without',
   b: true, // ERROR
 },
 {
   a: 'with', // ERROR
 }
];

拥有这样的区分属性在许多情况下非常有用,例如在条件逻辑中,因此您可能希望将这样的属性添加到数据 model 中。

if(item.a === "with") {
  console.log(item.b, item.c); // works, as item got narrowed down
}

据我所知,没有办法通过界面来做到这一点。 您可以在添加数据之前在代码中检查它。 一个属性可以有多个接口。

例如:

const someItem:接口A | 接口B | 不明确的;

您可以在使用更新值之前进行检查

 if(b) { someItem = value structured as InterfaceA } else { someItem = value structured as InterfaceB }

您还可以查看如何使用类和构造函数https://www.typescriptlang.org/docs/handbook/classes.html

多谢你们。 我得到了答案!

type ExcludeKeys<T> = { [P in keyof T]: never; };

type RequireOrExcludeKeys<T, Keys extends keyof T = keyof T> = Pick<T,Exclude<keyof T, Keys>> & (Required<Pick<T, Keys>> | ExcludeKeys<Pick<T, Keys>>);

type ItemProps = RequireOrExcludeKeys<{
   a: string;
   b?: boolean;
   c?: string;
}, 'b' | 'c'>;

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM