// 学习资源:
// 1、阮一峰TS教程:http://ts.xcatliu.com/
// 2、TS官网手册:https://www.typescriptlang.org/docs/handbook/intro.html
// 3、TS中文网:https://www.tslang.cn/
import { type } from "os"
import { pathToFileURL } from "url"
import { useState } from "_@types_react@16.14.21@@types/react"
import { Col } from "_antd@4.17.2@antd"
import { is } from "_immer@9.0.7@immer/dist/internal"
// TS简介
// TypeScript(微软) vs. Flow(脸谱)
// Angular vs. React
// TS被广泛运用于前端工程,大约在2020下半年(Vue3.0出现)
// TS > ES6 > ES5,TS是JavaScript的超集,它是静态语言。
// TS在前端工程化中,大多数的TS错误,热更新没法识别;只有当我们使用VScode时才能更好捕捉到TS的错误。
// 基础类型
const a0: boolean = true
const a1: number = 100
const a2: string = 'hello'
const a3: number | string = '100'
const a4: null = null
const a5: undefined = undefined
const a6: object = { a: 1 }
const a7: Array<number> = [1, 2, 3]
const a8: number[] = [2,3,4]
const a9: object[] = [{a:1},{b:2}]
const a10: Array<number[]> = [[1,1],[2,2],[3,3]]
const a11: Array<any> = [true, 3, 'hello', [1,2]]
// 元组:本质上也是一个数组,只不过数组中每个位置上的数据类型是确定的。
let a12: [string, boolean, object] = ['hello', true, {a:1}]
// any和void
// any表示任意类型(包括自定义类型)
// void表示没有类型(一般函数返回值)
let a13: any = null
a13 = 100
const a14: void = undefined
function foo(): void {
console.log('--')
}
foo()
// never 一般函数的返回值类型,表示这个函数没有“终点”
function die(): never {
while(true) {
console.log('---')
}
}
function middleware(): never {
throw(new Error())
}
// enum 枚举类型(数量有限,并元素各不相同)
enum Color { red, green, blue }
console.log(Color.red)
console.log(Color[0])
enum Cate { car='汽车用品', office='办公用品', chothe='男装女装' }
console.log(Cate.car)
// interface 定义一个接口(用于面向对象编程,如果你有兴趣自行搜索)
interface Shape {
leg: string,
arm: string
}
class People implements Shape {
leg = '1m'
arm = '2m'
}
// interface 自定义类型
interface User {
username: string,
password: string,
age: number,
addr?: string, // 可选的属性
readonly token?: string, // 只读属性,不能改
[propName:string]: any, // 支持扩展属性
child?: People,
four?: Shape,
run?: (start: string)=>boolean,
eat?(arg:number, arg2?:string):number
}
const zs: User = { username:'zs', password:'123', age:20, addr:'深圳' }
const ls: User = { username:'zs', password:'123', age:20, token:'tt' }
let ww: User = { username:'zs', password:'123', age:20 }
ww.gender = '男'
ww.mobile = '1000'
ww.child = new People()
ww.four = { leg: '1m', arm: '1m' }
ww.run = function () { console.log('run'); return 1===1 }
ww.run('深圳')
ww.eat = function() {return 20}
ww.eat(30,'40')
// type 类型别名
type Hybrid = number | string | boolean | object | null | Shape | User
const b1: Hybrid = 80
const b2: Hybrid = {a:1}
let b3: Hybrid = true
b3 = 90
// 类型字面量
type S = 'wentao' | 'abc' | 'ced'
const ss: S = 'abc'
type Female = { hair: string } | { makeup: ()=>void }
type Man = { work: ()=>void } & { clown: boolean }
// 类型联合 |
type Human1 = Female | Man
const h1: Human1 = { hair: '1m' }
const h2: Human1 = { work: ()=>console.log('work'), clown: true }
// 类型交叉
type Human2 = Female & Man
const h3: Human2 = { hair: '2m', work:()=>console.log('work'), clown: false }
// type 和 interface
// 1、type用于定义类型别名,可以进行类型交叉和类型联合。
// 2、interface用于自定义类型,还可以参与面向对象编程。
// 3、最佳实践:尽可能只使用interface,如果需要类型交叉或联合时必须用type。
// 函数类型(函数声明)
interface Menu {
path: string,
component: string,
icon: string,
[propName:string]: any
}
function arrToTree(arr:Array<Menu>): Array<Menu> {
// do something
return arr
}
arrToTree([{path:'/article',component:'',icon:''}])
type MathFn = (a:number, b:number)=>number
const add: MathFn = (a, b) => {
return a + b
}
const sub: (a:number, b:number)=>number = (a,b)=>a-b
add(1,2)
sub(2,1)
// 在函数声明时,可选参数必须放后面
function bar(a:string, b?:number, c?:boolean): void {
console.log(a)
console.log(b)
}
// 函数声明时,函数的返回值类型可以不用写,TS会进行默认“类型推断”
// 当可选参数有默认值时,不加?,带有默认值的可选参数不一定只能放在必填的后面。
function run(b:string='hello', a:string ) {
return a + b
}
run(undefined, 'world') // hello world
run('hi', 'world') // world hi
function car(a:number, ...rest:Array<number>): void {
console.log(a)
console.log(rest)
}
car(1,2,4,4,5,6,6,7)
// 函数重载
// 什么是函数重载?函数名相同,参数列表(参数个数、参数顺序、参数类型)、函数返回值,有一点差异就是“重载”。
function eat(a:string): void
function eat(a:number): void
function eat(x:boolean, y:boolean): void
function eat(a:any,b?:any): void {
if (typeof a === 'string') {
console.log('实现了第一个eat方法')
}
if (typeof a==='number') {
console.log('实现了第二个eat方法')
}
if (typeof a==='boolean' && typeof b==='boolean') {
console.log('实现了第三个eat方法')
}
}
eat('hello')
eat(200)
eat(true,false)
// 泛型
// 什么泛型?在函数声明、接口定义、类定义中,把不确定的类型用一个符号占位。当真实使用函数、接口和类时,再传入实际的类型。这就是泛型。
// function consoleSomething (a:string): string {
// console.log(a)
// }
// function consoleSomething (b:number): number {
// console.log(b)
// }
// function consoleSomething (a:boolean): boolean {
// console.log(a)
// }
function consoleSomething<T> (a:T): T {
return a
}
consoleSomething<number>(100)
consoleSomething<boolean>(true)
consoleSomething<number[]>([1,2,3,4])
function swap<T,U>(a:T, b:U): [U,T] {
// do something
return [b, a]
}
swap<number,string>(100,'200') // ['200', 100]
interface Dog {
name: string,
value: number
}
swap<number[], Dog>([1,2,3], {name:'dog',value:20}) // [{name:'dog',value:20},[2,3,4]]
// 泛型约束(不叫泛型推断)
interface He {
length: number,
width: number
}
type TT = string | Array<any> | He
function getLength<T extends TT>(arg:T) {
return arg.length
}
getLength<string>('zhangsan') // 8
getLength<string[]>(['a','b','c']) // 3
getLength<He>({length:20,width:10}) // 20
// 泛型在接口中的应用
interface Qf<T, U> {
teacher: T,
student: T,
work: (arg:U) => T
}
const szqf: Qf<string,number> = {
teacher: 'xia',
student: 'gp7',
work: (arg:number)=>(arg+'人')
}
console.log(szqf.teacher)
szqf.work(56) // '56人'
// 泛型在类定义中的应用
class Animal<T> {}
new Animal<string>()
new Animal<number>()
// 类型推断: (xx as type) 、 <type>xx
// 类型推荐只能“骗”过TS编译器,项目真实运行时该报错还是报错。
function consoleLength(arg:any) {
console.log((arg as string).length)
console.log(<string>arg.length)
console.log(<Array<any>>arg.length)
}
consoleLength(100)
consoleLength('hello')
consoleLength([1,2,3])
// 声明文件
// 作用:在TS环境,一些非TS的第三方包无法正常使用,要使用"声明文件"来处理。
// 特点:所有的声明文件都是以 .d.ts 结尾。声明文件只在包含在TS检测的目录内部,都可以起作用。
// 常识:以后在前端工程项目,只要看到了 .d.ts文件、@types/* ,都是为了处理第三方包在TS环境中的兼容性。
// 在TS项目中,如果安装了某一个包,但import(第三方包或文件模块)时报错、或者导入的undefined,这一定是因为缺少了“声明文件”,去社区寻找别人写好的声明文件;如果找不到,你自己写。
// 配置文件
// TS项目中的 tsconfig.json / jsconfig.json 就是TS的配置文件。
// TS配置文件被修改了,一般不用重启项目。
// 常用的配置选项有:compilerOptions、include、exclude、。。。。
// 编译选项(compilerOptions)有上百个选项。理论上所有的TS报错,都可以通过适当的编译选项进行关闭。
// TS编译报错 vs. ESLint报错:前者主要用于检测类型,后者用于检测代码规范。TS报错在VScode中会有更加友好的错误提示。
// TS核心库提供了很多JS、BOM、DOM的类型。
const dd: Date = new Date()