文章目录
一、数组
定义数组类型方法:
1、number[],boolean[]
let arr:(number|string)[]=[1,2,3,'a']
let arr2: any = [1, 'sadsad', true, {}]
let arr3: number[][] = [[1], [2]] //多维数组
2、Array 泛型,number表示成员类型,如果成员有其他类型可改为联合类型
let arr:Array<number> = [1, 2, 3];
let arr:Array<number|boolean> = [1, 2, 3];
let arr1: Array<Array<number>> = [[1], [2]] //多维数组泛型
3、定义对象数组使用interface
interface X {
name: string,
age?: number
}
let arr: X[] = [{ name: '小曼', age: 12 }, { name: '小修' }]
另外:下面示例中,X[number]表示数组X所有数值索引的成员类型,所以返回boolean。
type X= boolean[];
type member= X[number]; // boolean
type Y= boolean[];
type members= Y[0]; // boolean
二、元组
元组必须明确声明每个成员的类型。
问号只能用于元组的尾部成员,也就是说,所有可选成员必须在必选成员之后
let arr4: [number, string, boolean, {},number?] = [1, 'sadsad', true, {}] //元组
1.元组定义
代码如下(示例):
let arr4: [number, string, boolean, {}] = [1, 'sadsad', true, {}] //元组
2.只读元组
只读元组是元组的父类型,所以,元组可以替代只读元组,而只读元组不能替代元组。
代码如下(示例):
type t1 = readonly [number, number]; //只读元组
type t2 = [number, number];
let x:t2 = [1, 2];
let y:t1 = x; // 正确
x = y; // 报错
数组与元组的区别,数组类型是定义在[ ]外面的,而元组类型是定义在[ ] 里卖的
三、协变、逆变、双向协变
鸭子类型:
TS核心原则之一是类型检查时关注数据所具有的“形状”。我们称之为鸭子类型duck typing或者结构子类型structural subtyping。
interface A {
name: string
age: number
}
let c:A={
name: '222',
age: 22,
message:'123'
}
1.协变
interface A {
name: string
age: number
}
// 子类型
interface B {
name: string
age: number
sex: string
}
let a: A = {
name: '222',
age: 22,
}
let b: B = {
name: '333',
age: 22,
sex: '男'
}
// 协变
a = b //b能完全覆盖a里的类型
2.逆变、双向协变
interface A {
name: string
age: number
}
// 子类型
interface B {
name: string
age: number
sex: string
}
// 逆变(通常发生在函数上)
let fna = (params: A) => {
console.log(params);
}
let fnb = (params: B) => {
console.log(222);
}
//一定是安全的
fnb = fna //运行fnb时候还是执行fna ,还是执行主类型,
fnb({ name: '2222', age: 24, sex: '男' })
//赋值时只能多不能少
//值为协变,函数为逆变
// 双向协变
fna = fnb //开启strictFunctionTypes=false(最好不要这么做)此时会报错,要求有sex属性
四、Symbol类型
1.举例
let a1: symbol = Symbol(1)
let a2: symbol = Symbol(1)
console.log(a1, a2); a1 === a2 //false(内存地址不一样)
console.log(Symbol.for('11') === Symbol.for('11'));
let obj = {
name: 1,
[a1]: 111,
[a2]: 222
}
console.log(obj);
// for...in不能读到Symbol
for (const key in obj) {
console.log(key);
}
// Object.keys()也不能读到Symbol
console.log(Object.keys(obj));
// Object.getOwnPropertyNames()也不能读到Symbol
Object.getOwnPropertyNames(obj)
// Object.getOwnPropertySymbols可以读到
console.log(Object.getOwnPropertySymbols(obj))
// 完美方法(都可以拿到)
console.log(Reflect.ownKeys(obj));
2.Symbol生成器和迭代器
2.1生成器
function* gen() {
yield Promise.resolve('琳')
yield '超大碗'
}
const iterator = gen()
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历
for (let v of gen()) {
console.log(v);
}
2.2迭代器
原生具备Iterator接口的数据(可用于for of遍历)Array、Set、Map、String、Arguments、NodeList、TypedArray、
迭代器的语法糖 for…of
let set: Set<number> = new Set([1, 2, 3, 5, 1, 2, 6, 7]) //天然去重
for (const value of set) {
console.log(value);
}
//解构赋值(底层也是调用iterator)
let [a, b, c] = [4, 5, 6]
console.log(a, b, c);
2.3手动实现对象的for…of(iterator)
let obj = {
max: 5,
current: 0,
[Symbol.iterator]() {
return {
max: this.max,
current: this.current,
next() {
if (this.current === this.max) {
return {
value: undefined,
done: true
}
} else {
return {
value: this.current++,
done: false
}
}
}
}
}
}
for (let value of obj) {
console.log(value);
}
//输出0 1 2 3 4
五、类型断言(as关键词)
类型断言的使用前提是,值的实际类型与断言的类型必须满足一个条件。
下面例子中:expr是实际的值,T是类型断言,它们必须满足下面的条件:expr是T的子类型,或者T是expr的子类型。
expr as T
// 语法一:<类型>值
<Type>value
// 语法二:值 as 类型
value as Type
例子:
let fn = function (num: number | string): void {
console.log((num as string).length);
}
fn('123')
参考链接:https://wangdoc.com/typescript/assert
最后:有错误或不理解的地方请大家指出,谢谢大家~