理解重载解析、this 伪参数,以及支配函数可赋值性的型变规则。
在 Kodokon 中打开本课重载函数暴露一组公开签名,后面跟着单个实现签名。一个关键的规范要点:后者从外部不可见;只有声明的重载才能被调用。解析会从上到下遍历签名,并保留第一个兼容的:始终把最具体的签名放在最前面,否则它永远不会被选中。
function parse(input: string): number;
function parse(input: string[]): number[];
function parse(input: string | string[]) {
return Array.isArray(input)
? input.map((s) => s.length)
: input.length;
}
const single = parse("abc"); // number
const many = parse(["a", "bb"]); // number[]TypeScript 允许你在首位声明一个 this 伪参数。它在生成的 JavaScript 中被完全抹除:它是对调用上下文的一个纯静态约束,在启用 noImplicitThis 时进行检查。ThisParameterType 和 OmitThisParameter 工具类型让你能提取或移除它,这对于为打算配合 call、apply 或 bind 使用的函数建立类型至关重要。
function greet(this: { name: string }, msg: string) {
return `${msg}, ${this.name}`;
}
type Ctx = ThisParameterType<typeof greet>;
// { name: string }
type Fn = OmitThisParameter<typeof greet>;
// (msg: string) => string
const user = { name: "Ada", greet };
user.greet("Hello"); // "Hello, Ada"
// greet("Hi"); // error: missing this context型变描述可赋值性如何通过一个类型构造器传播。对于函数,返回类型是协变的,而在启用 strictFunctionTypes 时,参数是逆变的:一个接受更宽类型的函数可以替换一个接受更窄类型的函数,反之绝不可以。一个刻意的例外:以简写语法声明的方法的参数仍然是双变的,这是一个历史妥协,没有它 Array<Dog> 就无法赋值给 Array<Animal>。自 4.7 起,你可以用 in 和 out 来标注期望的型变,例如 interface Producer<out T>,编译器会对其进行验证。
interface Animal { name: string }
interface Dog extends Animal { bark(): void }
declare let f: (a: Dog) => void;
declare let g: (a: Animal) => void;
f = g; // OK: g accepts a wider type, that is safe
// g = f; // error with strictFunctionTypes
interface Sink { accept(a: Animal): void }
interface DogSink { accept(a: Dog): void }
declare let s: Sink;
declare let d: DogSink;
d = s; s = d; // both compile: bivariance!this 参数在生成的 JavaScript 中会怎样?