1. any和unkown的区别
any表示任意类型,可以被任何类型分配,也可以分配给任何类型
// any类型分配给其他类型
let val:any
let val_any:any=val
let val_unkown:unknown=val
let val_void:void=val
// 基本类型
let val_undefined:undefined=val
let val_null:null=val
let val_number:number=val
let val_string:string=val
let val_boolean:boolean=val
let val_never:never=val // 报错:不能将any类型分配给never
// 其他类型分配给any
val = '';
val = 1;
val = true;
val = null;
val = undefined;
val = unknown; // 报错,unknown 仅表示类型,但在此处作为值使用
val = never; // 报错,never仅表示类型,但在此处作为值使用
val = any; // 报错,any仅表示类型,但在此处作为值使用
val = void; // 应为表达式
unkown表示未知类型,可以被任何类型分配,不能分配给任何类型
// unknown 类型分配给其他类型
let val:unknown
let val_any:any=val
let val_unkown:unknown=val
// 基本类型
let val_undefined:undefined=val // 报错:不能将unkonwn类型分配给 undefined
let val_null:null=val // 报错:不能将unkonwn类型分配给 null
let val_number:number=val // 报错:不能将unkonwn类型分配给 number
let val_string:string=val // 报错:不能将unkonwn类型分配给 string
let val_boolean:boolean=val // 报错:不能将unkonwn类型分配给 boolean
// 其他类型分配给unknown
val = '';
val = 1;
val = true;
val = null;
val = undefined;
val = unknown; // 报错,unknown 仅表示类型,但在此处作为值使用
val = never; // 报错,never仅表示类型,但在此处作为值使用
val = any; // 报错,any仅表示类型,但在此处作为值使用
val = void; // 应为表达式
注意:代码规范,any虽然可以代表任意类型,但是能不用就不要用,这是默认的代码规范问题。
与any任意类型相比,因为unknown是未知类型,所以只能进行!!,!,?,typeof,instanceof等有限操作。
2. 数组和元组的区别
如果数组的类型在 [] 前面,那么表示该数组全部都是该类型。
如果数组的类型在 [] 内部(严格限制类型和元组的长度),那么表示该数组的第x个元素是该类型。
数组类型在 [] 前面
let arr:(number|string)[] = [1,2,3,'ss'] // 表示数组内部为数字或字符串类型
let arr:any[] = ['a',2,true] // 表示数组内部为任意类型
数组类型在 [] 内部的用法,此时为元组!
// 源具有3个元素,但目标仅允许1个
let arr:[number] = [1,2,3] // 报错,不能将 [number,number,number]分配给类型[number]
let arr:[number] = [1] // 正确
let arr:[string,number] = ['q',1] // 报错,多种类型数组,长度和类型必须对照
let arr:[string,number] = ['q',1] // 正确
let arr:[any,any,any] = ['a',1,true] // any元组也需要规定元素数量
注意:[string,boolean]这种声明形式指的是元组,即一个已知元素数量和类型的数组。
3. 索引签名和工具类型record的区别
Record工具类型的本质就是索引签名,不同之处只是用法,仅仅需要继承就可以,不需要再写一遍索引签名的用法。
索引签名的用法
interface objProp{
name:string;
age:number;
[k: string]:any;
}
let obj:objProp = {
name: 'wd',
age: 12
}
Record工具类型的用法
interface objProp extends Record<string,any>{
name:string;
age:number;
}
let obj:objProp = {
name: 'wd',
age: 12
}
// record工具类型的.d.ts声明文件源码
type Record<K extends keyof any, T> = {
[P in K]: T
}
4. interface和type的区别
如果开发一个包或者要被继承,使用接口interface
如果定义一个基础数据类型或者进行类型运算,那么使用类型别名type
interface可以进行声明合并,type不可以进行合并
// interface同名接口会自动进行声明合并
interface a{
name: string;
}
interface a{
age:number;
}
let u = {} as a;
console.log(u.name, u.age) // undefined 未赋值
// type类型别名不可以进行声明合并
type type_a = number;
type type_a = string; // 报错 标识符type_a重复
type可以直接进行赋值运算,interface必须先继承
// type可以进行类型运算
type type_a = number;
type type_sum = type_a| string
interface a{
name: string;
}
interface b extends a{
age:number;
}
let h = {} as b
console.log(h.age,h.name) // undefined undefined
interface只可以用于对象和函数,type可以用于对象,函数,基础类型,数组,元组
// interface
interface obj{
name: string
}
interface fun{
fn:(x:string) => void
}
// type
type obj = {name:string}
type fun = (x:string) = > string
type tBoolean = true
type tNull = null
type union = string|number
type arr = number[]
type tuple = [number,number]