添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

基础类型推断,最佳通用类型推断 都是从右往左的推断,根据表达式右侧的值来推测表达式左侧变量的类型。

上下文类型推断是从左往右的推断,通常出现在 事件处理 中。

类型推断 不符合你的要求的时候,你可以使用 类型断言 as

类型断言 可以增加代码的灵活性,在改造旧代码时非常有效,但是类型断言要 避免滥用 ,要对自己 上下文 充足的 预判 没有任何根据的类型断言 ,会给你的代码 安全隐患

基础类型推断

这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时。

1
2
3
4
5
6
7
8
// 初始化变量 x:number
let x = 3

// 设置默认参数值 x:number
let y = (x=1)=>{}

// 确定函数返回值 z:number
let z = (x = 1) => { x + 1}

最佳通用类型

当需要从几个表达式中推断类型时候,会使用这些表达式的类型来推断出一个最合适的通用类型。例如,

1
let x = [0, 1, null]

为了推断 x 的类型,我们必须考虑所有元素的类型。 这里有两种选择:number 和 null。 计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型。

由于最终的通用类型取自候选类型,有些时候候选类型共享一个公共结构,但是却没有一个类型能做为所有候选类型的超级类型。例如:

1
2
3
4
5
6
7
8
9
10
11
class Animal {
numLegs: number
}

class Dog extends Animal {
}

class Lion extends Animal {
}

let zoo = [new Dog(), new Lion()]

这里,我们想让 zoo 被推断为 Animal[] 类型,但是这个数组里没有对象是 Animal 类型的,因此不能推断出这个结果。 为了更正,我们可以明确的声明我们期望的类型:

1
let zoo: Animal[] = [new Dog(), new Lion()]

如果没有找到最佳通用类型的话,类型推断的结果为联合数组类型, (Dog | Lion)[]

上下文类型推断

有些时候,TypeScript 类型推断会按另外一种方式,我们称作 上下文类型 ;上下文类型的出现和表达式的类型以及所处的位置相关。通常出现在 事件处理 中,比如:

1
2
3
window.onmousedown = function(mouseEvent) {
console.log(mouseEvent.clickTime) // Error
}

这个例子会得到一个类型错误,TypeScript 类型检查器使用 window.onmousedown 函数的类型来推断右边函数表达式的类型。 因此,就能推断出 mouseEvent 参数的类型了,所以 mouseEvent 访问了一个不存在的属性,就报错了。

如果上下文类型表达式包含了明确的类型信息,上下文的类型被忽略。重写上面的例子:

1
2
3
window.onmousedown = function(mouseEvent:any) {
console.log(mouseEvent.clickTime) // OK
}

这个函数表达式有明确的参数类型注解,上下文类型被忽略。这样的话就不报错了,因为这里不会使用到上下文类型。

上下文类型会在很多情况下使用到。通常包含函数的参数,赋值表达式的右边,类型断言,对象成员,数组字面量和返回值语句。上下文类型也会做为最佳通用类型的候选类型。比如:

1
2
3
4
5
function createZoo(): Animal[] {
return [new Bee(), new Lion()]
}

let zoo = createZoo()

这个例子里,最佳通用类型有 3 个候选者:Animal,Bee 和 Lion。 其中,Animal 会被做为最佳通用类型。

类型兼容性

当一个 类型Y(源类型) 可以被赋值给另一个 类型X(目标类型) 时,可以说类型X兼容类型Y。

源类型必须具备目标类型的 必要属性

  • 结构之间兼容:成员少的兼容成员多的
  • 函数之间兼容:参数多的兼容参数少的
  • TypeScript允许在类型兼容的变量之间相互赋值,这个特性增加了语言的 灵活性

    接口兼容性

    接口之间相互兼容时,成员少的可以兼容成员多的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 接口兼容性
    interface X {
    a: any;
    b: any;
    }
    interface Y {
    a: any;
    b: any;
    c: any;
    }
    let x: X = { a: 1, b: 2 }
    let y: Y = { a: 1, b: 2, c: 3 }
    x = y
    // Property 'c' is missing in type 'X' but required in type 'Y'.
    y = x

    函数兼容性

    判断两个函数是不是兼容,通常发生在两个函数相互赋值的情况下,也就是函数作为参数的情况下。当给下面的高阶函数 hof 传递 参数 时,就会判断 参数 Handler 是不是类型兼容。 Handler 是目标类型 参数 是源类型

    要目标类型,兼容源类型需要满足3个条件:

  • 1)参数个数
  •