类型运算符而不是声明扩展 class 的接口

Type operator instead of declaring an interface that extends a class

According to typescript documentation,接口可以通过以下方式扩展类:

class C {
  f1: string;
  f2: number;
}

interface I extends C {};

请注意,我没有用额外的成员扩展 I,这就是正文 {} 为空的原因。

I 和 C 之间的区别当然是普通对象 { f1: "hi", f2: 3} 符合 I 但不符合 C (因为虽然它具有所有字段,但它没有' t 是由 C 的构造函数生成的)

我想知道,有没有类型运算符可以不用声明I就可以从C得到I?例如类似于 operator<C> 等同于 I 的东西(你甚至可以使用 type I = operator<C>?

根据您的预期用途,您实际上可能只使用 C 就没问题。例如:

class C {
  constructor(public f1: string, public f2: number){}
}

interface I extends C {}

function getF1(x: C) {
   return x.f1;
}

const x: C = { f1: "abc", f2: 123 };

getF1(x); // returns "abc"

请注意,当您在类型注释中使用 C 时,Typescript 实际上并不确保该对象确实是 C 的实例,而是确保它具有所有属性。 你写的不是真的,普通对象不“符合”C。根据 TS 类型系统,确实如此。

如果你有一个更复杂的 class 并且出于某种原因想要做一些事情,比如获取所有属性而不是方法,你可以使用 TS mapped type with a conditional type return 所有不是函数的属性。

总的来说,用TypeScript Playground来考察转译的结果总是值得的,以更好地了解classes和TS中接口的区别。

const sth = { foo: 100 };
const i: I = { f1: "hi", f2: 3};
const fakeC: C = { f1: "hi", f2: 3};
const trueC = new C("h1", 3);

// does it conform to type C at transpilation time?
function ofTypeC(x: C) { return true; }
// ofTypeC(sth); // error
ofTypeC(i); // true
ofTypeC(fakeC); // true
ofTypeC(trueC); // true

// does it conform to type I at transpilation time?
function ofTypeI(x: I) { return true; }
// ofTypeI(sth); // error
ofTypeI(i); // true
ofTypeI(fakeC); // true
ofTypeI(trueC); // true

// is it an instance of class C at run time?
sth instanceof C // false
i instanceof C // false
fakeC instanceof C // false
trueC instanceof C // true

或者可能为了更能说明使用 JS classes 作为 TS 类型的注意事项:

class Cat {
  public meow() {console.log("meow")}
}

class Dog {
  public meow() {console.log("Nah man")}
}

let cat: Cat = new Dog();
cat.meow();