TS回调函数参数似乎未完全检查

时间:2019-03-29 17:13:34

标签: typescript

TS接受一个回调函数,该回调函数需要一个将被调用的类型的子类,但不需要一个完全独立的类型。

这对我来说似乎是个错误,这有什么作用?

伪:

class A ...
class B extends A ...
class C ...
callWithA((a:A)=>void) ...
takeB(b:B) ...
takeC(c:C) ...
callWithA(takeB) // compiles fine, but will break at runtime
callWithA(takeC) // does not compile

完整示例:

class A {
    a: string;
}
class B extends A {
    b: string;
}
class C {
    c: string;
}
function callWithA(callbackfn: (value: A) => void): void {
    callbackfn(new A());
}
function callWithB(callbackfn: (value: B) => void): void {
    callbackfn(new B());
}

function takeA(a: A) {
    console.log('takeA got', a);
    console.log('#');
}

function takeB(b: B) {
    console.log('takeB got', b);
    console.log('#');
}

function takeC(c: C) {
    console.log('takeC got', c);
    console.log('#');
}

function takeString(s: String) {
    console.log('takeString got', s);
    console.log('#');
}

let a: A
a = new B();
let b: B;
// b = new A(); // incompatible, Good!
// takeB(new A()); // incompatible, Good!

callWithA(takeA); // takeA(a:A) will be called with an A, OK
callWithA(takeB); // BUG HERE ?! takeB(b:B) will be called with an A!! not good!
// callWithA(takeC); // incompatible, good, A is not a C
// callWithA(takeString); // incompatible, good

callWithB(takeA); // takeA(a:A) will be called with a B, OK
callWithB(takeB); // takeB(b:B) will be called with a B, OK
  // callWithB(takeC); // incompatible, good, A is not a C
  // callWithB(takeString); // incompatible, good

我希望编译器拒绝使用不兼容的回调'takeB'

我已经看到TS确实接受带有必需参数子类的调用函数,这可能会引起问题:

addDog(arr: Animal[]) {arr.append(new Dog())}
let cats: Cat[] = []
addDog(cats) // Works, since cats are animals, but then we get dogs in a array of cats

但这似乎有所不同,直接调用回调不会编译。

这是错误,还是“按设计”。

1 个答案:

答案 0 :(得分:1)

默认情况下,函数参数是双变量的。有一个编译器标志会将其变为错误,它被称为RadioGroup。使用此标志,您突出显示的呼叫将是一个错误。

您可以详细了解here