类型运算符而不是声明扩展 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();
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();