往期回顾:
目录
2.2 interface 和 type 区别二:声明对象类型
今天我们主要讲对于ts新增类型的约束及断言和泛型,东西有点多建议收藏,下面是TS新增的几种类型
- 联合类型
- 自定义类型(类型别名)
- 字面量类型
- 元组
- 枚举
- void
- any 等等……
1.联合类型
联合类型是我们比较常见的,一个值可以有多种类型,看代码👇
//数值和字符串二选一 只能选一个类型 不能多选
let str1: string | null = '';
let str2:string | number[] = [1,2]
//数组(有括号的) 可以共存 不加括号 不可共存
let str3:(number | string)[] = ['1',2]
2.类型别名(自定义类型)type
自定义类型可以自己定义的类型,接口也是自己定义的,类型别名和接口在定义简单类型的约束时是差不多的
共同点:
- 都可以描述一个对象或函数
- 都可以被扩展
不同点:
- type 可以声明基本类型别名,联合类型,元组等类型
- type 语句中还可以使用 typeof 获取实例的 类型进行赋值
- type 无法进行声明合并,interface可以重复定义,默认是自动声明合并
/*
type定义简单类型
*/
type MyNumber = number
type StringOrNumber = string | number
type MyBoolean = boolean
type Point = [number, number]
type Callback = (data: string) => void
2.1 interface 和 type 最直观的区别
//interface可以重复定义,会自动合并,但是必须保证同接口下的相同属性名类型一致
interface user {
userName:string
}
interface user {
age:number
}
//自动合并
interface user {
userName:string
age:number
}
/*
错误演示
interface user {
userName:number
age:number
}
报错信息:后续属性声明必须属于同一类型。
属性“userName”的类型必须为“string”,但此处却为类型“number”
*/
type A = number;
type A = string;
/*
报错信息:标识符“A”重复。
*/
2.2 interface 和 type 区别二:声明对象类型
//interface在定义对象属性时不会自带索引类型必须声明
interface MyInterface {
foobar: string
}
type MyType = {
foobar: string
}
const exampleInterface: MyInterface = { foobar: "hhh" }
const exampleType: MyType = { foobar: "hhh" }
let record: Record<string, string> = {}
record = exampleInterface
// interface 类型报错
// 不能将类型“MyInterface”分配给类型“Record<string, string>”。
// 类型“MyInterface”中缺少类型“string”的索引签名
record = exampleType
// type 不报错
2.3 interface 和 type 的扩展方式
interface
interface Person{
eat():void;
}
interface Child extends Person{
work():void;
}
/*
继承之后的 Child 接口
interface Child {
eat():void;
work():void;
}
*/
//或者可以定义一个新接口继承两个接口
interface MyInterface extends Person,Child{
study()void;
}
//类使用接口需要使用implements
class Sth implements MyInterface {
public name:string;
constructor(name:string){
this.name=name;
}
eat(){
console.log(this.name+'喜欢吃馒头')
}
work(){
console.log(this.name+'写代码');
}
study(){
console.log(this.name+'学习TS');
}
}
var w = new Sth('张三');
w.eat();
type
type Animal={
name:string
}
//给Animal扩展接口
type Bear=Animal&{
honey:boolean
}
interface SuperHuman extends Bear {
gender: string;
}
const bear: Bear= {
name: '维特维奇',
honey: true,
};
//or
const bear: SuperHuman = {
name: '维特维奇',
honey: true,
gender: '123',
};
3.Ts断言
类型断言的作用就是缩小值的范围手动指定值的具体类型
3.1 as
as 可以指定某一个值作为某种类型 看实例👇
type User = {
name: string;
age: number;
};
const user = {} as User;
//直接 . 就可以看到有什么属性
console.log(user.name);
//as通常使用于获取 DOM 元素的时候指定具体元素,来看下面实例
const box = document.getElementById('img')
console.log(box.src) // ts报错
const box = document.getElementById('img') as HTMLImageElment
console.log(box.src) //正确
let str:any = '我是一个字符串';
//当我们知道这个值一定是一个字符串的时候可以使用as string让他作为一个字符串类型
console.log(str.length)//虽然可以使用,但是这里.length是没有提示的
let len = str as string;
//这里就可以点出字符串的方法
console.log(str.length)
3.2 !非空断言
官方给出的解释是在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 !
可以用于断言操作对象是非 null
和非 undefined
类型。具体而言,x!
将从 x
值域中排除 null
和 undefined
。非空断言和 ?. 相反,这个符号表示对象后面的属性一定不是null或undefined。只有明确的知道这个属性不可为空,才可使用,下面请看实例
function fn(value: string | undefined | null) {
/**
* 错误信息
* 不能将类型“string | null | undefined”分配给类型“string”。
* 不能将类型“undefined”分配给类型“string”。ts(2322)
*/
const onlyString: string = value; // Error
const ignoreUndefinedAndNull: string = value!; // OK
}
//函数调用
type NumGenerator = () => number;
function fn(numberGenerator: NumGenerator | null) {
numberGenerator(); // Error 不能调用可能是 "null" 的对象。ts(2721)
numberGenerator!(); // OK
}
4.字面量类型
在TS中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型TS 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型。对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型;
let str: 'hello world' = 'hello world';
let num: 996 = 996;
let bool: true = true
//进阶
//字面量类型通常用于描述拥有明确成员的集合
type Direction = "up" | "down" | "left" | "right";
function getDirectionFirstLetter(direction: Direction) {
return direction.substr(0, 1);
}
getDirectionFirstLetter("help"); // error 类型"test"的参数不能赋给类型“Direction”的参数
getDirectionFirstLetter("left");
- 拓展
使用const定义的常量是不可更改的,会默认取赋值字面量的类型为他的类型,是只读的一个变量
但用let和var定义的变量的类型就变成了赋值字面量类型的父类型,例如下面代码str父类型就是 string ,num的、父类型就是number,以此类推。
let str = "hello world"; let num = 996; let bool = false; str = "welcome to bejing"; num = 669; bool = true;
5.元组类型
官方定义元组(Tuple)合并了不同类型的对象,元组可以属于理解成一个任意类型并且长度有限的数组 下面看实例👇
- 简单点说就是一个定长的任意类型的数组,只不过需要注意的是
- 数据的类型的位置和数据的个数,需要和 在定义元组的时候的数据类型和位置相一致
//正确示例 let tuple: [number, string, boolean] = [15, '两年半', true]; //错误示例 let tuple1: [number, string, boolean] = ['两年半', 123, true];
6.枚举
使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。枚举使用 enum
关键字来定义
且定义的枚举每一个值对应的下标与数组同理,也可自行定义下标值,下面看实例👇
enum myEnum {
'唱',
'跳',
'rap',
'篮球',
}
let array = ['唱', '跳', 'rap', '篮球'];
console.log(myEnum[1] == array[1]); //true
//上边说过枚举还可自己定义下标
enum myEnumTest {
'唱' = 3,
'跳',
'rap',
'篮球',
}
console.log(myEnumTest['唱'] == 3);//true
console.log(myEnumTest['篮球'] == 3);//true
本期内容到此结束啦,期待下期在于大家见面
最后祝大家都能坚持下去今天的心情像太阳一样温暖,明天的希望像星星一样灿烂!愿每一个心灵都有一份幸福,愿每一个梦想都有一个实现! 拜拜~~