一.类型注解
:number就是类型注解。 作用:为变量添加类型约束,约定了是什么类型,就必须是什么类型,不可更改。有哪些可以约束的类型呢?
JS 自有类型:
- 简单数据类型(原始类型)
- 复杂数据类型
TS新增类型
- 联合类型
- 自定义类型
- 接口
- 元祖
- 字面量类型
- 枚举
- void
- ...
let num: number = 12;
let str: string = 'hello';
let flag: boolean = true;
let temp1: undefined = undefined;
let temp2: null = null;
num = 13;
str = 'world';
flag = false;
temp1 = undefined;
temp2 = null
TS定义数组的两种方式
- const 数组名 = 类型[]
- const 数组名 = Array<类型>
const arr: number[] = [1, 2, 3, 4];
const strArr: string[] = ['a', 'b', 'c'];
// ------------------------------------
const arr1: Array<number> = [1, 2, 3, 4];
const arr1Arr: Array<string> = ['a', 'b', 'c'];
联合类型
需求:一个变量,既可以存数字,也可以存字符串
语法: let 变量名:类型1 | 类型2 | 类型3 = xxx (值的类型只能取约定好的类型)
let num: number | string | boolean = 11
num = 'hello';
num = true;
// -----------------------------
let arr: (string | number)[] = [1, 2, 3, 'a', 'b'];
let arr1: Array<string | number> = [1, 2, 3, 'a', 'b'];
类型别名(自定义类型)
需求:当一个数组里存在多种类型时,并且这几种类型很常见,也可以正好用来给其他数组使用。
语法: type 类型别名 = 类型1 | 类型2 | 类型3 | ...
type TestArr = (number | string | boolean)[];
// 这是定义数组的类型
const arr: TestArr = [1, 'a', true]
const arr1: TestArr = [2, 'b', false]
const arr2: TestArr = [3, 'c', true]
// -------------------------------------
type TestArr1 = number | string | boolean;
// 这种写法是定义数组的每一项可以取得类型
const arr3: TestArr[] = [1, 'a', true]
const arr4: TestArr[] = [2, 'b', false]
const arr5: TestArr[] = [3, 'c', true]
const arr6: Array<TestArr> = [22, 'aa', false]
函数类型
函数类型主要是给参数和返回值设置类型
语法: function 函数名(参数一:类型名,参数二:类型名):返回值的类型名{ }
const 函数名 = (参数一:类型名,参数二:类型名):返回值的类型名{}
function add(num1: number, num2: number): number {
return num1 + num2
}
add(1, 2)
const addFn = (n1: number, n2: number): number => {
return n1 * n2
}
addFn(3,6)
// 如果一个函数没有返回值,可以使用void来表示
const sayHi = (str1: string, str2: string): void => {
console.log(str1 + str2);
}
sayHi('hello', 'world')
// 函数类型的封装(只能在函数表达式/箭头函数中使用)
type TypeFn = (n1: number, n2: number) => void
const sumFn: TypeFn = (n1, n2) => {
return n1 + n2
}
sumFn(2, 5)
对象类型
语法 const 对象名:{属性名1:类型名,属性名2:类型名}={属性名1:属性值,属性名2:属性值}
const obj: { name: string, age?: number } = {
name: 'zs',
age: 18
}
// 如果需要设置某个属性为可选的 就在需要设置的那个属性的属性名后面加个?就可以了
type UserObj = { name: string, age?: number }
const person1:UserObj = {
name:'ls',
age:20
}
const person2:UserObj = {
name:'ww',
age:22
}
// ------------------设置可选属性
const person3:UserObj={
name:'zl'
}
对象中添加方法的类型校验
// 对象中方法的类型校验
type UserObj = {
name: string, age?: number, sayHi?(username: string): void, add?: (n1: string) => void
}
const person1: UserObj = {
name: 'ls',
age: 20,
sayHi(username) {
console.log('hello Word' + username);
},
add: (n1) => {
console.log(n1);
}
}
const person2: UserObj = {
name: 'ls',
age: 20,
}
接口类型 interface
语法 interface IObj {属性名:类型名,属性名:类型名} // 推荐接口名首字母用大写 ‘i’ 接口名后面不要 = 号
/*
接口类型 interface
type 和 interface 都可以定义对象类型 但是type是新语法 并且type可以定义的类型范围更广
interface推荐以I开头来命名 如: interface IObj
*/
// type Obj = {
// name: string,
// age: number
// }
interface IObj {
name: string,
age: number
}
const obj: IObj = {
name: 'zs',
age: 18
}
接口类型与type类型实现继承
/*
接口类型与type类型实现继承
*/
interface IPonit2D {
x: number,
y: number
}
interface IPonit3D extends IPonit2D {
z: number
}
const point:IPonit3D = {
z:300,
x:100,
y:200
}
type obj = {
name:string
}
type obj1 = {
age:number
} & obj
const person:obj1 = {
age:18,
name:'zs'
}
元祖类型
场景: 在地图中 使用经纬度坐标来标记位置信息 元祖类型是一种更严格的数组类型 适用于元素较少的数组 可以确切的标记出有多少个元素 并且知道每个元素对应的类型
/*
元祖类型
*/
let Point: [number,number] = [114.30,32.21];
let test: [string,number] = ['zs',18]
const [name ,age] = test
console.log(name.charAt);
console.log(age.toFixed);
字面量类型 一般情况下与联合类型(type)使用 作用是更准确的定义类型
/*
字面量类型
一般情况下与联合类型(type)使用
作用是更准确的定义类型
*/
type Gender = '男' | '女'
const zs: Gender = '男'
const pp: Gender = '女'
type Direction = 'up' | 'down' | 'left' | 'right';
function testDirection(direction: Direction) {
console.log('方向改变为' + direction);
}
枚举类型 定义一组命名常量(对象,收集键值对的方式)
语法:enum xxx {}
/*
没有指定值 就按照下标标记值
enum Direction {
up, // 0
down, // 1
left, // 2
right // 3
}
*/
// 也可以指定值
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right',
}
function changeDirection(direction: Direction) {
console.log('方向变为' + direction);
}
changeDirection(Direction.Down) // Down
changeDirection(Direction.Left) // Left
any类型 表示可以取任意类型 不进行类型校验 尽量不用
开发过程中 不确定类型 可以先用 any 占位 => 确认了类型格式后 => 在去改成具体类型
let temp:any = 2
temp = 'str'
temp = false
类型断言 有时候 你会比ts更明确一个值的类型,它的推断不一定准确或者ts也不知道推断什么类型、
// const A = document.createElement('a') // 这个 A ts就能帮我们推断出类型了
const a = document.querySelector('#box') as HTMLAnchorElement
if (a) {
console.log(a.href);
}
// const Img = document.createElement('img')
const img = document.querySelector('.image') as HTMLImageElement
if (img) {
console.log(img.src);
}
const img1 = <HTMLImageElement>document.querySelector('.image')
if (img1) {
console.log(img1.src);
}
泛型:可以将类型当做参数传递
场景:类型不要写死 根据传参类型来确定类型
/*
泛型,可以将类型当做参数传递
场景:类型不能写死 根据传参类型来确定类型
*/
function id<T>(t:T):T {
return t
}
type Num = number
id<Num>(1)
id<string>('hello')
id<boolean>(false)
泛型约束(单个参数)
// 泛型约束
interface ILength {
length:number
}
function id<Type extends ILength>(value:Type):Type {
console.log(value.length);
return value
}
id<string>('a')
// id<number>(11) // 只有符合Ilength条件的函数才能调用
泛型约束(多个参数)
function getprop<Type extends object, key extends keyof Type>(obj: Type, key: key) {
return obj[key]
}
const temp = {
name:'zs',
age:19
}
getprop(temp,'age')
getprop(temp,'name')