定义
//以逗号结尾
type Person={
name:string,
age:number
}
//以分号结尾
type Person={
name:string;
age:number
}
const person:Person={
name:'Tom',
age:18
}
对象的定义变量之间可以用逗号隔开也可以用分号,个人建议用逗号
type Person={
name:string,
age:number
}
const person:Person={
name:'Tom',
age:18
}
delete person.name//报错
person.name='Jack'//正确 定义的属性只能修改不能删除
person.sex//报错 不能访问不存在的属性
可选属性 属性后边加问号
type Person={
name:string,
age?:number
}
const person:Person={
name:'Tom';
}
和其他可选参数一样,上边的age?:number相当于 age:number|undefined,但是不能写成后者的形式
只读属性 属性前边加readonly
type Person={
name:string,
readonly age:number
}
const person:Person={
name:'Tom',
age:18
}
person.age=19//报错 age是只读属性
只读属性只能在初始化的时候赋值,后边不能修改
type Person={
name:string,
readonly hobby:string[]
}
const person:Person={
name:'Tom',
hobby:['打游戏']
}
person.hobby.push('看书')
如果只读属性是一个对象,只要不直接赋值改变地址就可以
type A={
name:string,
age:number
}
type B={
readonly name:string,
readonly age:number,
}
const a:A={
name:"Alice",
age:25
}
const b:B=a
a.age++
console.log('b.age:',b.age);
上边是一种特殊情况,把一个可读写类型的对象赋值给只读的对象,修改可读写对象,这个只读对象也会修改。同样的把只读赋值给可读写,依旧可以修改,也算个bug吧。
可以像读取对象属性一样读取类型的属性赋值给别的类型
type A={
name:string,
age:number
}
type name=A['name']
属性名的索引类型
type A={
a:string,
b:number,
[property:number]:string,
}
let a:A={
a:'hello',
b:123,
1:'world',
5:'456'
}
有时后端返回的参数不固定,就可以使用这个索引类型,property可以写成别的值,建议就写成这个把通俗易通。 只能存在一个索引类型
type A={
[property:number]:number,
}
let a:A=[0,1,2];
console.log(a.length)//报错
虽然可以把数组赋值它,但是尽量不要这样做,编辑器还是认为它是一个对象,不会有数组的方法的
对象的解构
let {a,b}={a:5,b:6};
解构属性起别名
let {a:c,b:d}=obj;
//等同于
let c=obj.a
let d=obj.b
因为:被占用所以,只能用别的办法定义类型,于是有了下边的这种
let {a:c,b:d}:{a:number,b:number}={a:5,b:6};
这样写其实定义的是c和d,就有点别扭了,老铁们记住就行了
结构类型原则
type A={
x:number
}
type B={
x:number,
y:number,
}
B包含A的所有属性,这种情况下B满足A的结构特性,所有的以B类型定义的值都可以赋值给以A定义的值
type A={
x:number
}
type B={
x:number,
y:number,
}
let b:B={
x:5,
y:10,
}
let a:A=b;
这种情况是为了迎合js项目而设计的,不管有多少属性,只要满足我提供的属性,就认为是同一类型,某些特殊情况下也会出现一些奇葩问题
type myObj = {
x: number,
y: number,
};
function getSum(obj: myObj) {
let sum = 0;
for (const n of Object.keys(obj)) {
const v = obj[n]; // 报错
sum += Math.abs(v);
}
return sum;
}
ts认为你传递的obj还可能包含除x,y的其他属性,换句话说它认为可能存在myObj里没有的属性,实际情况下调用函数时别的属性也传不进来,会报错的。只能额外记录下这种情况,解决下
type myObj = {
x: number,
y: number,
};
function getSum(obj: myObj) {
let sum = 0;
for (const n of Object.keys(obj) as (keyof myObj)[]) {
const v = obj[n]; // 报错
sum += Math.abs(v);
}
return sum;
}
用断言直接告诉ts,它就是myObj的属性
严格字面量检测
type myObj = {
x: number,
y: number,
};
let obj: myObj = {
x: 1,
y:2,
c:6//报错
};
如果是直接字面量赋值,会启动严格检验模式,
最小检测
如果一个对象的所有属性都是可选属性,当赋值时,ts的检查机制是要么你是空对象,要么你至少包含一种属性
type Options = {
a?: number;
b?: number;
c?: number;
};
const opts = { d: 123 };
const obj: Options = opts; // 报错
你可以把opts赋值为空对象,或者至少包含a,b,c的一种,或者你更改类型
type Options = {
[property:string]:number;
};
空对象
const obj={};
obj.name='张三'
因为ts的类型推导,obj的类型会被推导为{},当赋值时就会报错了