TypeScript 高级类型
1. 类型别名
类型别名用来为类型起个新名字。
type Name = string;
let nameValue: Name = "张三"
type Point = {
x: number;
y: number;
add: (x: number,y: number) => number
}
let point: Point = { x: 100,y: 200,add: (x: number,y:number)=> x + y}
请仔细观察一下代码中存在的问题
let pizzaSize: 'large' | 'medium' | 'small' = 'medium'
function selectPizzaSize(size: 'large' | 'medium' | 'small') {
pizzaSize = size
}
selectPizzaSize('small')
上面这段代码同一个类型被定义了多次,重复的代码太多,时可以直接用类型别名type 创建类型,从而复用类型
type Size = 'large' | 'medium' | 'small';
let pizzaSize: Size = 'medium';
function selectPizzaSize(size: Size) {
pizzaSize = size
}
selectPizzaSize('large')
2.联合类型
联合类型可以将变量设置为多种类型。
// 联合类型: 为一个变量设置多个类型
let a: string | number | boolean = true;
//arg 参数即可以时字符串类型也可以是数值类型
function fn(arg: string | number) {}
fn("a")
fn(10)
在使用联合类型的变量时,默认只能使用联合类型中所有类型中的公共属性,因为TypeScript 编译器并不能确定它的具体类型是什么,所以不能准确的列出它的下面有哪些属性和方法
在大多数情况下,在使用联合类型的变量时,需要现缩小变量的类型范围,尽量让ts编译器列出更加准确的属性和方法
3.交叉类型
交叉类型是将多个类型叠加合并组成新的类型,新类型包含了所有被合并类型的所有属性
type Draggable = {
drag: ()=> void;
}
type Resizable = {
resize: () => void
}
type UIWidget = Draggable & Resizable;
let textBox: UIWidget = {
drag: () => {},
resize: () => {}
}
4.字面量类型
字面量类型即可以设置变量的类型,又可以限制变量的取值范围。
字面量值的类型就是变量的类型,字面量值就是变量的取值范围。
type Quantity = 50 | 100;
// TS2322: Type '54' is not assignable to type 'Quantity'.
let quantity: Quantity = 54;
type Metric = "cm" | "inch";
// TS2322: Type '"abc"' is not assignable to type 'Metric'.
let metric: Metric = "abc";
可空类型
在TypeScript中,undefined和 null 这两个值本身也可以作为类型使用
//undefined
let uf: undefined = undefined
//null
let nl:null = null
function greet(name: string | null | undefined) {
if( typeof name === "string") {
console.log(name.toLowerCase())
} else {
console.log("wrong")
}
}
greet(undefined)
5.可选链操作符
可选链操作符( ?. ) 允许开发者通过链的方式访问一个对象上可能为null 或 undefined 的属性,并且不用检查中间的属性是否为空
type Customer = {
birthday?: Date
}
function getCustomer(id: number): Customer | undefined | null {
return id === 0 ? null : {birthday: new Date()}
}
let customer = getCustomer(0)
// if (customer !== null && customer !== undefined) {
// if (customer.birthday !== undefined) {
// console.log(customer.birthday);
// }
// }
console.log(customer?.birthday?.getFullYear());
let array: string | number[] | null = [0, 1, 2];
console.log(array?.[0]);
let log: any = (message: string) => console.log(message);
log = null;
log?.("Hello");
6.空值合并运算符
空值合并操作符(??) 是一个逻辑操作符,当左侧的操作数为 null 或者 为 undefined 时, 返回其右侧操作数,否则返回左侧操作数。
let speed: number | null = null;
let ride = {
speed: speed ?? 30
}
7.类型断言
通过类型断言可以覆盖TypeScript 编译器的推断,当开发者比 TypeScript 更加清楚它的类型时使用。
//const phone: HTMLElemnt | null
const phone = document.getElementById("id");
console.log((<HTMLInputElement>phone).value);
console.log((phone as HTMLInputElement).value)
8.unknown 类型
unknown 是更加严格的 any 类型,在对 unknown 类型的变量执行操作之前必须进行先假设它的类型。
let anything: unknown = "Hello TypeScript";
anything = true;
anything = 3.14
anything = function() {}
// TS2571: Object is of type 'unknown'. ❎
// console.log(anything.length);
if (typeof anything === "number") {
anything.toFixed();
} else if (typeof anything === "string") {
anything.toUpperCase();
} else if (typeof anything === "function") {
anything();
}
9.never 类型
如果一个函数永远都不会有返回值,可以指定函数的返回值类型为 never。
const throwError = (message: string): never => {
throw new Error("error")
}
//const throwError: (message:string) => void
const throwError = (message: string) => {
if(!message) throw new Error("error")
}
注意:如果一个函数永远都不会有返回值,说明函数调用位置后面的的代码永远都不会被执行