启用TS
将TS编译成JS的方法
-
通用方法:webpack + babel
-
新的方法:Vite2(有默认配置)
运行create-vite-app ts-vite-demo-1 --template react-ts 创建了react-ts类型的文件,文件名为ts-vite-demo-1,然后yarn ,再运行yarn dev
ts和tsx的区别:tsx = ts + jsx ,ts = ts ,webpack + ts = ts + jsx
- 手动使用:tsc(TypeScript compiler)
终端运行tsc 1.ts,将 ts文件 编译为 js文件,然后再运行node 1.js
类型 V.S. 类
ts语法:
var x:string = 'hi' //string是类型的一种
JS的基本类型:
-
简单类型:null,undefined,string,number,bool,bigint
-
复杂类型:object
这里的类型是指数据的类型(type),在JS里面有一个关键词是typeof,是用来获取一个东西的类型
typeof有两个著名的bug:1、如果typeof后面接的是函数,那么返回的就是function;2、如果typeof后面接的是null,那么返回的就是object
JS 中的类
JS中的类只研究基本类型中的object,这个类是人为发明的,面向对象编程
面向对象编程:1、基于class关键字的面向对象编程;2、基于原型的面向对象编程
- 基于class:
class Person = {
属性1
属性2
属性3
方法1
方法2
方法3
}
const p1 = new Person()
const p2 = new Person()
- 基于原型
function Person() {
var temp = {}
temp.属性1
temp.属性2
temp.属性3
temp.方法1
temp.方法2
temp.方法3
temp.__proyo__ = 共有属性
return temp
}
const p1 = Person()
p1.属性1
p1.方法1()
类型和类的区别: 类型的英文是type,类型是对所有数据的分组(数据的天然分类);类的英文是class,类是对象的抽象编程(等价于class关键字,类就是对对象的人为的一种设计方法(就是创造一个对象,需要先声明一个类,用类new出一个对象))
类型的两个好处
- 减少bug
不用运行就知道运行时的bug
- 提示
随时随地进行类型的匹配
TS支持的JS类型
const a:undefined = undefined
const b:null = null
const c:string = 'hi'
const d:boolean = true
const e:symbol = Symbol('hi')
const f:bigint = 123n
const g:number = 123
//前面这样写,除了object
const obj:Object = {} //类
const obj0:object = [] //类型
//两者没有明显区别,但是一般情况下将类型具体化
const arr:Array<string|number|null> = [] //告诉arr,里面的内容是string或number或null
//函数写法
//const add = (a,b) => a+b
const add1 = (a:number,b:number):number => a+b //接受a是number,b是number,返回值也是number(返回值在箭头的前面写)
const add2: (a:number, b:number)=> number = (a, b) => a + b
type Add = (a:number, b:number)=> number
const add3:Add = (a, b) => a + b
//以上3中写法都可以,但是一般用第三种写法
//如果想要描述一个函数接受一个a和b,返回一个和,同时它自身有一个属性
interface AddWithProps{
(a: number, b: number) : number
xxx: string
} //意思是它是一个函数,它的第一个参数是a,第二个参数是b,返回的值是number
// 声明一个函数,它有xxx属性
const add4:AddWithProps = (a, b) => a + b
add4.xxx = 'yyy'
//1. 类型写在函数体(具体参考 add1)
//2. :后面(具体参考add2)
//3. type 缩写(具体参考add3)
//4. 有属性,只能用 interface(具体参考add4)
export{}
TS中的any、unknown、void、never、enum、tuple
any
let a: any = 'hi'
any没有任何限制
unknown
let b: unknown = JSON.parse('{"name":"lily"}')
unknown要用的话,必须明确它是什么东西
any和unknown的区别:unknown不是手写出来的值,而是从外界获取到的值。any是永远不知道是什么类型,可以是任何类型;而unknown是现在不知道但是用的时候必须明确知道是什么类型
void
let print: () => void = function(){console.log(1)}
print()
void就是不要函数的返回值
never
如果代码中让一个东西变成了never,说明代码出错了
type Dir = 1 | 2 | 3 | 4 | undefined
let dir: Dir
switch (dir){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case undefined:
break;
default:
console.log(dir)
break
}
never表示空集,什么都没有,既不是undefined也不是null,表示不应该存在的,没有这个类型,例如:
type X = number & string
//等价于type X = never
tuple
元组
let p: [number, number] = [100,200]
let p1: [number, string] = [100, 'x']
let p2: [number, string, boolean] = [100, 'x', true]
意思为p是一个元组,元组就是不可变更长度的数组,如果想要固定一个数组的长度就是元组,然后把每一个元素的类型写上 元组只是TS里面的概念,JS里面不存在元组
enum
枚举
enum Dir2 {东,南,西,北}
let d: Dir2 = Dir2.东
let d2: Dir2 = Dir2.西
console.log(d)
type Dir3 = '东'|'男'|'西'|'北'
let dir2: Dir3 = '东'
let dir3: Dir3 = '西' //建议使用这种写法
枚举就是把数字0,1,2,3,4变成一个对应的标志,是标志而不是字符串,只有TS认识这个标志,JS不存在这个标志。
总结
-
JS和TS都有的类型:
null,undefined,number,string,Boolean,symbol,bigint,object(classNametypeinterface) -
TS 独有的类型:
any,unknown,never,enum(枚举),tuple(元组)
给不同数据加type
const fn: (a: number) => number =
function (x){return x + 1}
const a: Array<number> = [1,2,3] //可以理解为Array是个函数,它接受一个参数;调用Array这个函数,它接受number
-
第一种语法是冒号后面加个类型
-
第二种语法就是类型后面加个尖括号,就是传参,叫做泛型;泛型就是给这个类型传个参数
如果要描述一个对象的类型的时候,不要再用object,而是用它对应的class,如果是数组,它的class就是Array,如果是函数,它在TS中"Function"不是泛型类型,要写成箭头函数的形式。
class是类型还是值?
既是值又是类型
// var x:类型 = 值
class A {
}
const B = A // JS
const a:A = new A() // TS 声明一个A的实例,那么等号前面的A是类型,等号后面的A是值
export {}
对于JS来说,A就是一个值;对于TS来说,它是类型,那么A的类型是object。
联合类型与区分联合类型
联合类型(|) and 交叉类型(&)
联合类型
- 联合类型
const f = (n: string | number)=>{}
- 类型推测
type A = {
name: string;
age: number
}
type B = {
name: string;
gender: String;
}
const f = (n: number | B) => {
if(typeof n=== 'number') {
n.toFixed() //TS预测这里的n是number
}else{
n.name //TS预测这里的n是B
} //这个时候可以toFixed,是因为TS会做类型收展,通过代码会预测n的类型
}
export {}
TS在写代码的过程中就能猜到n的类型,在一个分支是多少,在另一个分支是多少
- 区分联合类型
type A = {
name: 'a';
age: number
}
type B = {
name: 'b';
gender: String;
}
const f = (n: A | B) => {
if(n.name === 'a'){
n.age // n是A类型
}else{
n.gender // n是B类型
}
}
export {}
需要这两个类型必须有一个相同的key,这个key叫什么无所谓,只要是相同的就好
必须用if...else做出两个分支选择,只要做出一个分支选择,那么TS就会知道n的类型
交叉类型
交叉类型&不能用于简单类型,简单类型就是除了object以外的7种类型。简单类型之间是没有交叉的
type A = {name:string} & {age:number}
const a:A = {
name: 'lily',
age: 18
}
&一般用于连接两个复杂类型
如果叠加一个类型,会成never,如果A成never了,后面不管是什么都会报错