当前位置: 首页 > 知识库问答 >
问题:

类与接口作为Typescript中的类型[重复]

寇丰
2023-03-14

我最近遇到了这个问题,我不确定是使用接口还是类来定义特定的类型。

注意:这个问题不是问接口之间的区别。

例如,给定这个类和接口

interface IMyClass {
  foo: string;
  bar: () => string;
}

class MyClass implements IMyClass {
  foo = 'foo';
  bar() {
    return 'bar';
  }
}

我将使用类或接口作为函数参数中的类型。

function identityByClass(value: MyClass): MyClass {
  return value;
}
function identityByInterface(value: IMyClass): IMyClass {
  return value;
}

在我看来,两者都可以,但我更喜欢使用类来避免同步接口上的所有方法/属性。我认为接口只是一个类必须遵守的模板/契约。

但是,在我的例子中,大多数情况下,该类通常会添加更多不在接口定义中的方法/属性。

下面这个类就是一个很好的例子。

class MyClassPlus implements IMyClass {
  foo = 'foo';
  bar() {
    return 'bar';
  }
  doMore() {
    console.log('more stuff here!');
  }
}

在这种情况下,我不能再交替使用这两个。

任何指向最佳实践的链接都很好。谢谢

共有2个答案

支洋
2023-03-14

使用接口定义类型的一个好处是,编译后接口本身被消除。这减少了应用程序的总体膨胀,这是在这种情况下使用接口的有力理由。

你可能会发现这很有用:https://jameshenry.blog/typescript-classes-vs-interfaces/

索瀚海
2023-03-14

我不确定是使用接口还是类来定义特定类型。

类和接口都创建一个类型,因此原则上它们可以互换使用。正如您所指出的,接口就像一个公共契约,而类实现了这个契约。

但是考虑以下情况:

  1. 如果您需要更改MyClass,怎么办

重构后的MyClass的新类型签名可能不再有效地用作函数中的函数参数。所以你需要重构所有的消费者-嗯...使用单独的类型接口,这种情况更不可能发生。

第2点示例:客户机可能会想到获取MyClass的静态属性(通过隐藏实现细节,接口不会让它变得明显):

class MyClass {
  static baz(){}
  foo = 'foo';
}

function identityByClass(value: MyClass) {
  console.log((value.constructor as any).baz) // function baz()
  // there we go. do something with static baz() method of MyClass
}

顺便说一下:这不仅仅是关于接口和类类型。类型别名提供了强大的功能,如映射或条件类型、联合等,并且大多数情况下都可以用于接口。

但是,在我的例子中,大多数情况下,该类通常会添加更多不在接口定义中的方法/属性。

您不需要同步类和接口类型。为了保持干燥,我想到了两个选择:

  1. 接口可以扩展类类型定义,以消除冗余声明

我更喜欢第二点,而不是所有其他选择,因为它遵循信息隐藏或松散耦合等设计原则。示例:

class MyClass {
  foo = 'foo';
  tooMuchDetail = "hide me"
}

// just pick, what we need (foo here)
type OnlyNeededProps = Pick<MyClass, "foo">

function doSomethingWithFoo(a: OnlyNeededProps) {
  a.foo
  a.tooMuchDetail // error, unknown (OK)
}

doSomethingWithFoo(new MyClass())
 类似资料: