如何为TypeScript接口强制实施至少一个可选属性中的至少一个?

时间:2019-12-30 08:32:37

标签: typescript

我想为可能具有属性“ a”或“ b”的对象声明一个接口

interface myInterface {
    a ?: string;
    b ?: string;
}

使a和b均为可选。我想要类似的东西

interface myInterface {
    a|b ?: string;
}

(Edit1)扩展大小写

interface myInterface 
{ 
    mustHaveProp1 : number;
    a|b : string;
    mustHaveProp2 : string;
    b|d|e : number;
}

2 个答案:

答案 0 :(得分:2)

您不能使用界面来执行此操作,而是可以使用联合来执行此操作。这个想法是要生成一个联合,其中我们每个联合组成部分都具有与原始类型相同的属性,但是需要一个属性,因此对于myInterface,我们需要类似{ a: string, b?: string } | { a?: string, b: string }的东西。

上述并集(在大多数情况下)也等效于以下交点myInterface & ({ a : string } | { b: string }。 (如果我们在&|之间应用分配属性,我们将得到(myInterface & { a: string }) | ((myInterface & { b: string }),并且由于在每个交集处,一个属性同时显示为可选项和必需项,因此必需项胜出。)

接下来的主要问题是如何从myInterface开始创建该联合,而不必明确地将其写出。为此,我们可以使用映射类型从原始类型获取每个属性,然后创建每个成员组成部分,然后对类型进行索引以获取所有这些新类型的并集。然后,我们可以与原始类型相交:

interface myInterface {
  a?: string;
  b?: string;
}

type OneProp<T> = {
  [P in keyof T]-?: Record<P, T[P]>
}[keyof T]

type RequireAtLeastOne<T> = T & OneProp<T>

let o1: RequireAtLeastOne<myInterface> = {} // err no properties
let o2: RequireAtLeastOne<myInterface> = { a: "" } // a present, ok
let o3: RequireAtLeastOne<myInterface> = { b: "" } // b present, ok
let o4: RequireAtLeastOne<myInterface> = { a: "", b: "" } // a and b present, ok

Playground Link

答案 1 :(得分:0)

type IModal = {content:string; content_object ?:未定义} |               {content_object:object;内容?:未定义}

相关问题