【问题标题】:How define an Interface with Optional values, but one of them Mandatory - TypeScript如何定义具有可选值的接口,但其中之一是强制性的 - TypeScript
【发布时间】:2018-03-27 10:12:41
【问题描述】:

我如何定义一个具有几个 Optional 值的 TypeScript 接口,但其中一个(或多个)是 Mandatory ???

假设我有以下代码:

interface ISearchKey
{
  name?: string;
  id?: number;
}

function findItem(search: ISearchKey): Item 
{
  // ... 

  return ...
}

我希望实现ISearchKey 接口的对象具有“名称”值和/或“id”值。可以发出其中之一(“name”和“id”),但不能同时发出!

我知道我可以通过验证 findItem() 函数中的输入来解决这个问题:

let name = search.name || "";
let id   = search.id   || -1;

或任何其他类型的输入验证,但这可以使用 TypeScript 类型验证吗?

【问题讨论】:

    标签: typescript interface optional


    【解决方案1】:

    联合类型,例如

    type ISearchKey = { name: string } | { id: number }
    
    const test = (key: ISearchKey) => console.log(key);
    
    test({ name: "name" });
    test({ id: 12 });
    test({ name: "name", id: 12 });
    test({ fail: true }); // Errors
    

    对于需要的属性,可以相交:

    // With mandatory data
    type ISearchKey2 = ({ name: string } | { id: number }) & { data: any };
    
    const test2 = (key: ISearchKey2) => console.log(key);
    
    test2({ name: "name" }); // Error
    test2({ name: "name", data: 0 });
    test2({ id: 12 }); // Error
    test2({ id: 12, data: 1 });
    test2({ name: "name", id: 12 }); // Error
    test2({ name: "name", id: 12, data: 2 });
    test2({ fail: true }); // Still Errors
    

    正如 @jcalz 所指出的,这些联合允许对另一个属性进行不同类型的输入,只要其中一个属性存在,例如

    { name: "name", id: "not a number!" }
    

    更正确的类型联合是:

    {name: string, id?: number} | {name?: string, id: number}
    

    这将保留可选属性的正确类型。

    【讨论】:

    • 什么是“类型”关键字?它与“界面”有何不同?如何将它与始终强制的数据一起使用,例如:{ id?: number; name?: string; data: any } /* data is always mandatory */
    • type 主要用于类型别名和组合。它与接口定义非常相似。
    • @GilEpshtain:很高兴它有帮助:)
    • 我会建议像{name: string, id?: number} | {name?: string, id: number} 这样的东西,因为只有{name: string} | {id: number} 将允许可能不受欢迎的值,比如{name: 'okay', id: 'whoops'}
    猜你喜欢
    • 1970-01-01
    • 2021-08-22
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    • 2017-01-14
    • 2021-08-27
    相关资源
    最近更新 更多