【问题标题】:How to make sure an interface only include properties from another interface?如何确保一个接口只包含另一个接口的属性?
【发布时间】:2019-09-26 16:04:54
【问题描述】:

假设我有以下界面。

interface Client {
  id: number;
  email: string;
  firstName: string;
  lastName: string;
  cellNumberFull: string;
}

我希望下面的接口只包含GoClient 中存在的属性。

interface ClientRestricted {
  firstName: string;
  lastName: string;
  cellNumberFull: string;
  foo: string; // This would throw an error
}

寻找一些与扩展相反的国王。有这种事吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    我倾向于让您的界面扩展一个映射的条件类型,它本身就是一个函数。这是一个递归类型定义(称为F-bounded quantification),可以让您做一些相当强大(如果令人困惑)的类型约束。例如:

    type Restrict<T, U> = { [K in keyof U]: K extends keyof T ? T[K] : never };
    type RestrictClient<U> = Restrict<Client, U>;
    
    // okay as desired
    interface Okay extends RestrictClient<Okay> {
      firstName: string;
      lastName: string;
      cellNumberFull: string;
    }
    
    // error, as desired
    interface Extra extends RestrictClient<Extra> {
      //      ~~~~~
      // Types of property 'foo' are incompatible.
      // Type 'string' is not assignable to type 'never'.
      firstName: string;
      lastName: string;
      cellNumberFull: string;
      foo: string;
    }
    

    通过使您的新界面I extends RestrictClient&lt;I&gt;,当且仅当I 可分配给RestrictClient&lt;I&gt;,这意味着如果I 可分配给{[K in keyof I]: K extends keyof Client ? Client[K] : never},这意味着如果@ 的每个键K 987654330@ 存在于Client 中,并且属于相同(或更窄)的类型。

    这也给出了以下行为,可能会或可能不会解决您的用例:

    // okay to narrow properties
    interface Narrowed extends RestrictClient<Narrowed> {
      firstName: "specificString";
    }
    
    // error to widen properties
    interface Widened extends RestrictClient<Widened> {
      //      ~~~~~~~ <-- number not assignable to string
      firstName: string | number;
    }
    
    // error to change property to unrelated types
    interface Unrelated extends RestrictClient<Unrelated> {
      //      ~~~~~~~~~ <-- number not assignable to string
      firstName: number;
    }
    

    如果它与您要查找的内容不完全匹配,您可以更改Restrict 的定义以使其更接近。无论如何,希望这能给你一些想法。祝你好运!

    Link to code

    【讨论】:

      猜你喜欢
      • 2021-12-14
      • 1970-01-01
      • 2021-05-16
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-29
      相关资源
      最近更新 更多