eco*_*747 5 typechecking typescript
我在非严格模式下遇到问题,这是我的代码,我可以将类型错误的函数分配给类型化变量。
我做错了吗?
谢谢。
interface A {
f1( ) : void;
}
interface B extends A {
f2( ) : void;
}
interface C {
f3( ) : void;
}
type expectA = ( a: A ) => void;
type expectB = ( b: B ) => void;
function testA( a: A ) {
console.log( "a" );
}
function testB( b: B ) {
console.log( "b" );
}
function testC( c: C ) {
console.log( "c" );
}
let v1: expectA = testA; // ok: assign type A to a type A
let v2: expectA = testB; // ok: assign type B (extending A) to a type A
let v3: expectA = testC; // fail -> normal: error TS2322: Type '(c: C) => void' is not assignable to type 'expectA'.
let v4: expectB = testA; // ok -> **abnormal**: there is no error in !strict mode
Run Code Online (Sandbox Code Playgroud)
TypeScript 实际上是在保护你不做一些愚蠢的事情,但它是以一种令人困惑的方式这样做的。
让我们将示例简化为仅包含接口A和B。
interface A {
f1( ) : void;
}
interface B extends A {
f2( ) : void;
}
type expectA = ( a: A ) => void;
type expectB = ( b: B ) => void;
function testA( a: A ) {
a.f1();
}
function testB( b: B ) {
b.f1();
b.f2();
}
const v1: expectA = testA;
const v2: expectA = testB; // error: Property 'f2' is missing in type 'A' but required in type 'B'
const v3: expectB = testB;
const v4: expectB = testA;
Run Code Online (Sandbox Code Playgroud)
乍一看,底部的结果只有v2一个错误,这似乎违反直觉。如果B扩展A,那么为什么不能在任何可以使用的B 地方A使用呢?
答案是因为我们在这里处理函数。仔细看看 的实现testB()。它调用该属性b.f2()是因为它期望其参数b具有该属性。但 的 左侧const v2: expectB相当于类型(a: A) => void。type的参数A没有. 因此,我们告诉 TypeScript 正确类型是什么是相互矛盾的;要么它是一个在这种情况下调用不安全的函数,要么它是一个在这种情况下调用是安全的函数。这是一个悖论!f2()v2a: Aa.f2()b: B
(请记住,这与是否testB 实际尝试调用无关b.f2();重点是,根据其参数类型的设置方式,它可能会导致场景中的运行时错误v2。)
现在,const v4你说你认为这是“不正常的”,这应该没问题,但如果我们再次仔细查看这些功能,我们会发现这是有道理的,这是可以的。如果将类型A或B变量传递给testA(),则不会出现错误,因为它永远不会尝试访问该f2()属性。
另请注意,它extends在 TypeScript 中的工作方式并不像您期望的那样。简单的写interface B extends A就是B会继承 的所有属性A。它不建立任何允许B代表 的任何实例的关系A。这种行为称为“多态性”,要做到这一点,您需要使用类,例如class B extends A implements A。
class A {
foo = '';
}
class B extends A implements A {
bar = '';
}
let isA = new A();
isA = new B(); // this is fine because B implements A
let isB = new B();
isB = new A(); // error: Property 'bar' is missing in type 'A' but required in type 'B'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
59 次 |
| 最近记录: |