“这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战”
TS中的强制类型转换
先看一个例子:
type T = {
title: string
}
type U = {
color: string
}
let result = <T&U>{}
result.title = '北京'
result.color = 'red'
如果我们写了一个空对象,需要给这个对象添加属性,这个时候是会报错的:
let result = {}
// 报错:提示不存的属性
result.title = '北京'
这个时候我们需要进行强制类型转换:
type T = {
title: string
}
let result = <T>{}
// 不会报错了
result.title = '北京'
你也可以进行类型断言
type T = {
title: string
}
let result = {};
(result as T).title = '北京'
注意写法有很多种
type T = {
title: string
}
type U = {
color: string
}
let result = {} as T;
result.title = '北京'
交叉类型
上面示例中使用到了交叉类型
interface A {
name: string;
sex: number;
}
interface B {
age: number;
sex: number;
}
type C = A&B
let c:C = { name: 'xxx', age: 18, sex: 1 }
既是A的子类型,又是B的子类型,既要满足A又要满足B
type AA = string | number;
type BB = string | boolean;
type CC = AA & BB;
那么CC是string类型
TS中的unknown类型
我们可以对 any 进行任何操作,不需要检查类型。
let value:any;
value = ture;
value = 1;
value.length;
没有类型检查就没有意义了,跟写JS一样。很不安全。
也可以把任何值赋值给 unknown
let value:any;
value = ture;
value = 1;
但是不能调用属性和方法
value.length; // 错误写法
如果需要调用属性和方法,那么你可能需要类型断言
let value:unknown;
value = 'hello';
(value as string).length
再或者使用类型保护
let value:unknown;
value = 'hello';
if (typeof value === 'string') {
value.length
}
联合类型中的 unknown定义
如果联合类型中有unknown,那么最终得到的都是unknown类型
type U1 = unknown | null;
type U2 = unknown | string;
type U3 = unknown | number;
类型别名 U1,U2,U3 都是 unknown 类型
ts的类型兼容性
你要的我有就可以,没有就不行
1、接口兼容性
interface Person1 {
name: string
}
interface Person2 {
name: string;
age: number;
}
let obj1: Person1 = {
name: 'xxx'
}
let obj2: Person2 = {
name: 'xxx',
age: 18
}
obj2 = obj1 // 错误:无法赋值,因为缺少属性,多了不影响,但是少了属性绝对不行
obj1 = obj2 是可以的
2、基本类型的兼容性
let num1: number
let num2: number | string
num1 = 10;
num2 = 'xxx'
num1 = num2 // 错误:无法赋值,因为缺少类型,多了不影响,但是少了类型绝对不行
num2 = num1 是可以的
3、类的兼容性
class Animal {
name: string
}
class Bird extends Animal {
age: number
}
let a: Animal;
let b = Bird;
b = a // 错误:无法赋值,因为缺少类型,多了不影响,但是少了类型绝对不行
a = b 是可以的
4、函数的兼容性
type Func = (a: number, b: number) => number;
let sum: Func;
function f1 (a: number, b: number):void {
// todo
}
sum = f1 // 错误:无法赋值,因为返回值类型不同
除了对比参数,还要对比返回值
type Func = (a: number, b: number) => number;
let sum: Func;
function f1 (a: number, b: number, c: number):number {
return a
}
sum = f1 // 错误:无法赋值,多了参数不行,但是少参数可以
type GetPerson = () => {name: string, age: number};
let getPerson :GetPerson;
function g1 () {
return {name: 'xxx'}
}
function g2 () {
return {name: 'xxx', age: 18}
}
function g3 () {
return {name: 'xxx', age: 18, sex: 1}
}
// getPerson = g1; 报错
// getPerson = g2; 正常
// getPerson = g3 正常
参数可以传自己和自己的父类,返回值可以传自己和自己的子类
条件类型约束
泛型约束的例子:
type MessageOf<T extends { message: unknown }> = T["message"];
在此示例中,我们使用 message: unknown 约束泛型T。
如果我们想 MessageOf 支持任何类型,我们可以通过将约束和条件类型一起使用:
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;
如果条件成立,在 true 分支内,TypeScript 知道 T 将具有一个 message 属性。否则将会返回 never 类型。
typeof
获取一个值的类型
type T = {
title: string
}
let person:T = {
title: 'hello'
}
let user = {
title: 'js'
}
// typeof 表示获取一个值的类型
type U = typeof user;
ReturnType
获取函数返回值的类型
function getUser() {
return {name: 'xxx', age: 10}
}
type GetUserType = typeof getUser;
type ReturnUser = ReturnType<GetUserType>
获取函数参数的类型
function getUser() {
return {name: 'xxx', age: 10}
}
type GetUserType = typeof getUser;
type ReturnUser = Parameters<GetUserType>
泛型约束
我们定义一个接口来描述约束条件。创建一个包含 .length 属性的接口,使用这个接口和 extends 关键字来实现约束:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}