1 JS与TS的数据类型
-
JS(8种)
number boolean string bigint symbol
null undefined
object (含Array Function Date..)
-
TS
JS 8种
void never enum unknown any
- 自定义类型
interface type(type严格来讲算类型别名)
2 理解TS的数据类型
- 从集合的角度理解TS数据类型
- 即每一个type都表示类型的集合
&表示交集;|表示并集
1
2
3
4
|
type number = 1 | 1.1 | 1.11 | ... | 2 | ... ;
type string = 'a' | 'ab' | ... ;
type boolean = true | false ;
type Object = {?} | Array | Function | String | Number | Boolean | ... ;
|
2 描述number、boolean和string的数据类型
- 先说结论:使用小写的
2 vs new Number(2)
1
2
3
4
5
6
7
8
9
|
var a = 2
// 内存中会以二进制的形式开辟值为2的空间
var b = new Number(2)
// {
// constructor:...
// toFixed:...
// toString:...
// valueOf: () => 2
// }
|
1
2
|
const a = 10
a.toFixed(2) //为什么一个值身上会存在toFixed方法?
|
- 说明JS包装了这个a,使其具有了Number实例对象的属性与方法
- 正是由于包装对象机制的存在,给人一种“JS一切皆对象”的假象
- JS中的Number、String和Boolean只用于包装对象,不适合作为数据类型
3 描述普通对象的数据类型
使用Object或object去描述对象的数据类型,太过于宽泛,类似any
所以一般使用索引签名或Record泛型来描述普通对象
1
2
3
4
5
|
// 表示对象的key为string,value为number
// 索引签名(k为任意小写字符)
type A = { [k: string]: number }
// Record泛型
type A = Record<string, number>
|
4 描述数组对象的数据类型
使用Array去描述数组的数据类型,太过于宽泛,一般使用
Array<?>
string[]
[string, number]
1
2
3
|
const a:Array<number> = [1, 2, 3]
const b:string[] = ['a', 'b']
const c:[1, 2] = [1, 2]
|
5 描述函数对象的数据类型
使用Function去描述数组的数据类型依然不够精确,一般使用箭头函数(?) => ?
1
2
|
type Func = (a:number) => number
const func:Func = (a) => a + 1
|
1
2
3
4
5
6
7
|
type FuncWithThis = (this: Person, name: string) => void
type Person = { name: string, func:FuncWithThis }
const func:FuncWithThis = function(hello){
console.log(hello, this.name)
}
const p:Person = {name: 'gsq', func}
p.func('hello')
|
6 其他对象
直接用class描述,例如
1
2
3
4
5
|
const d:Date = new Date()
const r:RegExp = /a+b/
const m:Map<string, number> = new Map()
const wm:WeakMap<{name:string}, number> = new WeakMap() // WeakMap的key必须是对象
const s:Set<number> = new Set()
|
7 any、unknown和never
1
2
|
const a:unknown = axios.get(...)
(a as number).toFixed(2)
|
- never是空集合,表示不应该出现的类型,出现说明出错了
1
2
3
4
5
6
7
8
9
|
type A = string & number // never
// 在类型判断中检查类型用
type A = string | number
let a:A
if(typeof a ==='string'){}
else if(typeof a === 'number'){}
else {
// 此时a为never,表示此处不应该对a进行操作
}
|
8 enum类型
-
使用enum的两种情况
1
2
3
4
5
6
7
8
9
10
|
// 定义
enum S {
todo = 0,
done,
deleted
}
let status = 0
// 使用
status = S.todo
status = S.done
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
enum Permission {
None = 0, //0000
Read = 1 << 0, //0001
Write = 1 << 1, //0010
Delete = 1 << 2,//0100
Manage = Read | Write | Delete // 0111
}
const user = {
permission: 0b0101
}
// 与计算 只有1&1才为1
// a&b===b 说明a有b的所有1
if((user.permission & Permission.Write) === Permission.Write) {
console.log('有写权限')
}
|
-
不使用enum的情况
1
|
type S = 'done' | 'working' | 'stop'
|
9 type和interface
9.1 type
- 类型别名(Type Aliases)
- 给其他类型取个外号,并不会产生新的类型
1
2
|
type Name = string
type FalseLike = false | 0 | null | undefined | ''
|
9.2 interface
1
2
3
4
5
|
interface Data { [k: string]: string }
interface Point { x: number; y: number }
interface Points extends Array<Point> {}
interface Fn { (x: number, y: number): number }
interface Data2 extends Date {}
|
- interface就是把type能做的事用面向对象的思想翻译了一下(非绝对)
9.3 区别
-
interface只描述对象的属性;type则描述所有数据类型
-
type只是别名;interface则是类型声明
-
type不可重新赋值,不方便扩展;interface具有自动合并的特性,方便扩展
- 对外API尽量用interface,对内尽量用type
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 自动合并,不会覆盖
interface X { name: string }
interface X { age: number }
const x:X = { name: 'gsq', age: 20 }
// 扩展已经存在的interface custom.d.ts
import { AxiosRequestConfig } from 'axios'
declare module 'axios' {
export interface AxiosRequestConfig {
_mock?: string
}
}
// 扩展全局的String
declare global {
interface String {
padZero(length: number): string
}
}
|