将ts编译成js的方法:
- webpack + babel
- Vite 2
- tsc ( typescript compiler )
使用vite2
vite/packages/create-vite at main · vitejs/vite
- create-vite-app ts-demo --template react-ts
- yarn
- yarn dev
类型 vs 类
类型 type
JS基本类型:null、undefined、string、boolean、number、symbol、bigint、object
typeof 有两个bug:
- typeof 函数 === function
- typeof null === object
类 class
JS 中的类只研究8种类型种的object,类是人为发明的
面向对象编程有两种:
- 基于class关键字
- 基于原型
类型的两个好处
- 减少bug
- 智能提示
Typescript语法
支持js的8个类型
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 obj:object = {} const arr:Array<string|number|null> = ['1', '2', 3, null]
函数有四种写法:
- 类型写在函数体
const add = (a:number, b:number):number => a + b
- :后面
const add:(a:number, b:number)=>number = (a, b)=> a + b
- type缩写
type Add = (a:number, b:number) => number
const add:Add = (a,b) => a+b
- 有属性,只能用 interface
interface AddWithProps {
(a:number, b:number):number
xxx: string
}
const add:AddWithProps = (a,b) => a+b
add.xxx = 'xxx'
typescript自己的类型
1、any 可以是任何类型
let a:any = 'hi'
a.name
a = 1
2、unknown 用时需要明确是什么类型
type C = {name: string}
type E = {age:number}
let b: unknown = JSON.parse('{"name": "frank"}')
console.log((b as C).name) // 断言
console.log((b as E).name) // 报错
3、void 描述函数,不要写return
let print: (a:number) => void = function(a){
console.log(a)
}
4、never
let c: never = null //报错
let c: never = undefined //报错
console.log(c) //报错
never 类型不能赋值,不能使用
那有什么用?
如果你的代码中让一个东西变成never,说明你的代码出错了,举例说明
type Dir = 1 | 2 | 3 | 4 | undefined
let dir: Dir = 1
switch(dir){
}
所以 never 就是不应该存在的,或者就是没有的
type X = number & string
X 的类型就是never
5、元组
let p: [number, number] = [100, 200]
p = [1,2,3,4] // 报错
6、枚举
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
console.log(c) // 1
下面写法类似
type Dir = '东' | '南' | '西' | '北'
let dir:Dir = '东'
console.log(dir) // 东
class
Object、Array、Function
class是值也是类型
联合类型 |
type A = {
name: string,
age: number
}
type B = {
name: string,
gender: string
}
const f = (n:number | B) => {
if(typeof n === 'number'){
n.toFixed()
}else{
n.name
}
}
收窄类型:
type A = {
name: 'a',
age: number
}
type B = {
name: 'b',
gender: string
}
const f = (n: A | B) => {
if(n.name === 'a'){
n.age
}else{
n.gender
}
}
交叉类型 &
& 不能用于简单类型 如 type A = number & string A 类型为 never
type A = {name:string} & {age: number}
const a:A = {
name: 'frank', // name 和 age 都要写,不然报错
age: 18
}
如果两边都有age,A为never
type A = {name:string, age: string} & {age: number}
泛型
type Add<T> = (a: T, b: T) => T
const addN: Add<number> = (a,b) => a + b
const addS: Add<string> = (a,b) => a + ' ' + b
泛型的实际应用
import React, {FunctionComponent} from 'react'
type P = {
name: string
}
const app: FunctionComponent<P> = (props)=>{
props.name
props.children
return <div>hi</div>
}
重载
例子1: 实现当a,b为number时,return a + b
当a,b为string时,return a + ' ' + b
例子2:
type Options = {headers?: any}
function get(url: string, options?: Options): void
function get(options: Options & {url: string}): void
function get(url: string | (Options & {url:string}), options?: Options):void{
if(arguments.length === 1){
const myOptions = url as {url: string} & Options
console.log(myOptions.url);
console.log(myOptions.headers);
}else{
console.log((url as string))
}
}
get('/xxx', {headers: 'get'})
get({url:'/xxx', headers:'get'})
如何用泛型封装网络请求库
type User = {
id: string | number;
name: string;
age: number;
}
type Response<T> = {
data:T
}
type T = Partial<Omit<User, 'id'>>
type CreateResource = (path: string) => {
create: (attrs:Omit<Partial<User>, 'id'>) => Promise<Response<User>>;
delete: (id: User['id']) => Promise<Response<never>>;
update: (id:User['id'], attrs: Omit<Partial<User>, 'id'>) => Promise<Response<User>>;
get: (id: User['id']) => Promise<Response<User>>;
getPage: (page: number) => Promise<Response<User[]>>;
}
const createResource = (path:string)=>{
return {
create(attrs: Omit<Partial<User>, 'id'>){
const url = path + 's'
return axios.post<User>(url, {data: attrs})
},
delete(){},
update(){},
get(){},
getPage(){}
}
}
var userResource = createResource('/api/v1/user')