【问题标题】:Interface with conditional properties带有条件属性的接口
【发布时间】:2019-01-28 19:11:38
【问题描述】:

我有一个特殊类型定义如下:

interface HasNoName {
  hasName: false;
}

interface HasName {
  hasName: true;
  name: string;
}

type MySpecialType = HasNoName | HasName;

有没有办法把MySpecialType写成接口?它需要是一个接口,因为我想要一个类来实现它。我不会写:

interface MySpecialType extends HasNoName, HasName {}

当我得到错误时:

“'HasName' 和 'HasNoName' 类型的命名属性 'hasName' 不是 一样的。”

【问题讨论】:

  • 如果您说HasNoNamehasName 设置为false,而HasName 则相反,那么当您将它们组合在一起时,您希望MySpecialType 拥有什么?听起来你可能只需要一个界面,比如Nameable { hasName: boolean; name?: string; }
  • 基本上我想知道是否可以从联合类型创建接口。您推荐的界面可以工作,但并不完美,因为我希望对执行以下操作的人具有类型安全性:const foo: Nameable = { hasName: true };.
  • 对我来说,设置falsetrue 是一种实现。所以我可能有 2 个像 class HasNoName implements Nameable { hasName = false; } class HasName implements Nameable { hasName = true; name: string; } 这样的课程。也许其他人有更好的主意!
  • 如果const truethy=()=> true; const foo: Nameable = { hasName: truthy() }; 怎么办?你认为 TS 应该评估表达式并相应地进行类型检查吗?
  • 不应该是interface HasNoName { hasName: boolean; } interface HasName { hasName: boolean; name: string; } 吗?

标签: typescript class interface


【解决方案1】:

你不能真正从联合类型中创建一个接口。但是如果你真的需要这个,你可以创建像它们实现联合类型一样的类......但它涉及一些type assertions,因为编译器无法轻松验证你在做什么。

举个例子:创建一个类来实现你可以实际实现的最接近的东西......就像{hasName: boolean, name?: string}

class _MySpecialClass {
  public hasName: boolean;
  public name?: string;
  public constructor();
  public constructor(name: string);
  public constructor(name?: string) {
    this.hasName = (typeof name !== 'undefined');
    this.name = name;
  }
}

这有一个overloaded 构造函数,用于标记HasNameHasNoName 之间的区别。

然后创建一个名为MySpecialClass 的命名值和命名类型,它被声明为按照你想要的方式运行。在此示例中,命名类型 MySpecialClass 只是联合 MySpecialType,而命名值 MySpecialClass 是断言以按照您想要的方式运行的 _MySpecialClass 构造函数。

type MySpecialClass = MySpecialType;    
const MySpecialClass = _MySpecialClass as {      
  new(name: string): HasName;
  new(): HasNoName;
};

并使用它进行测试:

const mySpecialInstance: MySpecialClass = 
  Math.random()<0.5 ? new MySpecialClass() : new MySpecialClass("Fred");

嗯,看起来不错。它有一些缺点,但根据您的用例,它可能对您有用。希望能帮助到你。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2011-01-02
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    相关资源
    最近更新 更多