Appearance
类型拓宽
类型拓宽
类型拓宽:初始值字面量推断出来的类型
字面量类型拓宽
字面量类型拓宽条件
- 通过 let,var 定义的变量、函数形参、对象非只读属性,指定了初始值
- 未显式添加类型注解
ts
let str = 'this is string' // 类型是 string
let strFun = (str = 'this is string') => str // 类型是 (str?: string) => string;
const specifiedStr = 'this is string' // 类型是 'this is string'
let str2 = specifiedStr // 类型是 'string'
let strFun2 = (str = specifiedStr) => str // 类型是 (str?: string) => string;添加类型注解限制类型拓宽
js
{
const specifiedStr: 'this is string' = 'this is string' // 类型是 '"this is string"'
let str2 = specifiedStr // 即便使用 let 定义,类型是 'this is string'
}特定类型拓宽
通过 let、var 定义的变量如果满足未显式声明类型注解且被赋予了 null 或 undefined 值,则推断出这些变量的类型是 any
js
{
let x = null // 类型拓宽成 any
let y = undefined // 类型拓宽成 any
/** -----分界线------- */
const z = null // 类型是 null
/** -----分界线------- */
let anyFun = (param = null) => param // 形参类型是 null
let z2 = z // 类型是 null
let x2 = x // 类型是 null
let y2 = y // 类型是 undefined
}案例:定义了一个 Vector3 接口,然后定义了 getComponent 函数用于获取指定坐标轴的值
ts
interface Vector3 {
x: number
y: number
z: number
}
function getComponent(vector: Vector3, axis: 'x' | 'y' | 'z') {
return vector[axis]
}问题:x 会被自动扩宽为 string
ts
let x = 'x'
let vec = { x: 10, y: 20, z: 30 }
// 类型“string”的参数不能赋给类型“"x" | "y" | "z"”的参数。
getComponent(vec, x) // Error解决:使用 const 声明 x
js
const x = 'x' // type is "x"
let vec = { x: 10, y: 20, z: 30 }
getComponent(vec, x) // OK对于任何给定的值都有许多可能的类型
js
const arr = ['x', 1]
/*
('x' | 1)[]
['x', 1]
[string, number]
readonly [string, number]
(string | number)[]
readonly (string | number)[]
[any, any]
any[]
*/下面的例子中,变量 x 的类型被推断为字符串
js
let x = 'semlinker'
x = 'kakuqo'
x = 'lolo'以下代码也合法,一般规则是,变量的类型在声明之后不应该改变,但 TypeScript 试图在特殊性和灵活性之间取得平衡。
js
let x = 'x'
x = /x|y|z/
x = ['x', 'y', 'z']控制类型拓宽
非原始值类型拓宽
const:使用 const 会将值限制为 字面量
数组和对象类型拓宽
js
const obj = {
x: 1
}
obj.x = 6 // ok
obj.x = '6' // Type 'string' is not assignable to type 'number'
obj.y = 8 // Property 'y' does not exist on type '{ x: number; }'TypeScript 默认行为:通过属性初始化来推断属性类型
覆盖默认行为
通过提供显式注解,覆盖默认行为
js
// Type is { x: 1 | 3 | 5; }
const obj: { x: 1 | 3 | 5 } = {
x: 1
}const 断言
const 断言,ts 将它推断出最窄的类型,没有拓宽。
区别:不同于 let 和 const 中的 const,这里 const 是类型级构造,在值空间中引入符号。
js
// Type is { x: number; y: number; }
const obj1 = {
x: 1,
y: 2
};
// Type is { x: 1; y: number; }
const obj2 = {
x: 1 as const,
y: 2,
};
// Type is { readonly x: 1; readonly y: 2; }
const obj3 = {
x: 1,
y: 2
} as const;