零碎记录一些ts要点
一,最近需要扩展Funcion类型,增加一个布尔类型的属性值。
1,可以自定义类型 又名 交叉类型
type OwnFunc = Function & { once?: boolean }
2,也可以声明接口
interface OwnFunc {
():any
once?: boolean
}
二,ts中,接口interface 与class之间相互的关系
A: 接口可以继承接口,类可以继承类。
B: 类可以实现接口,但是接口只能约束这个类的公共成员,也就是说接口定义的属性方法等,类必须要设置未公共成员,不能为protected 和 private
例:
interface Girl {
name: string;
age?: number;
bust: number;
}
// 报错
class G1 implements Girl {
name: string
age: number
protected bust: number
}
// 正确
class G2 implements Girl {
name: string
age: number
bust: number
}
三,联合类型
var name : 'Kev'| 'Kevin' | 'Vincent' | 'Vin' // 只能为4个字符串中的一个
var val: string | number // 为字符串或者数字
四,索引类型
A, keyof T
表示T所有公共属性的联合类型
interface T {
name: string
age: number
}
var p: keyof T
p 只能赋值为字符串 name
或者 age
B, T[K]
代表对象T
的属性K
所代表的类型
C, T extends U
泛型的继承,泛型如果继承一个属性,表示这个泛型变量可以通过继承获取U的公共属性
实例:获取对象的一组属性值
bad:
function getValues(obj: any, keys: any[]) {
return keys.map(key => obj[key])
}
const obj = {
name: 'kevin',
age: 18
}
console.log(getValues(obj, ['name', 'age']))
console.log(getValues(obj, ['work', 'salary'])) // 没有ts约束报错
good:
function getValuesNew<T, K extends keyof T>(obj: T, keys: K[]): T[K][] {
return keys.map(key => obj[key])
}
console.log(getValuesNew(obj, ['name', 'age']))
console.log(getValuesNew(obj, ['work', 'salary'])) // 有ts约束报错
五,映射类型
interface Obj {
name: string;
age: number;
gender: string;
}
// 将Obj映射为一种新的类型,该类型所有属性是可读的
type ReadonlyObj = Readonly<Obj>
// 将Obj映射为一种新的类型,该类型所有属性是可选的
type PartialObk = Partial<Obj>
// 将Obj映射为一种新的类型,该类型只有name 和 age属性
type NewObj = Pick<Obj, 'name' | 'age'>
// 将Obj映射为一种新的类型,该类型只有 name 和 age属性
type NewObj2 = Omit<Obj, 'gender'>
// 将Obj映射为一种新的类型,该类型的属性名全部为Obj的属性,类型为指定类型
type k = keyof Obj
type NewObj3 = Record<k, Number> // 现在NewObj3与Obj类型有同样属性名,但是类型全部为Number
// Exclude 排除T中可以赋值给U的类型
type Exclude<T, U> = T extends U ? never : T
type newObj4 = Exclude<'a'| 'b', 'a'|'c'> // 现在newObj4 为'b'
// Extract 抽取T中可以赋值U的类型
type Extract<T, U> = T extends U ? T : never;
type newObj5 = Extract<'a'| 'b', 'a'|'c'> // 现在newObj4 为 'a'
// 资料: 一些工具泛型 https://zhuanlan.zhihu.com/p/40311981
六,扩展一个依赖库
比如我们已经有了一个依赖库moment 我们这样写
import moment from 'moment'
declare module 'moment' {
export function myFunction():void
}
// 这样不会报错
moment.myFunction = ()=>{ console.log('do your own thing') }
七,ts里面 es module 与commonJS module
由于ES module 除了有允许默认的顶级导出,还可以有单独的导出。比如这这样:
// es1.ts导出代码
export default function () {
console.log('default')
}
export a = 1 // 将会生效
// es module 引入代码
import defaultFunc from './es1.ts'
import { a } from './es2=1'
但是commonJS module,只允许有一个默认的顶级导出。
// node.a.ts 导出代码
// 与顺序无关,只要有module.exports, 都会覆盖掉exports.* = * 的声明
module.exports = function() {
console.error('杰西卡')
}
exports.a= 1 // 将不会生效
// commonjs module 引入代码
var cm = require('./node.a.ts')
// cm 是一个函数
特殊情况下,commonjs(node) module 必须要引用es module,ts提供了一个特殊的语法 export
关键字,ts会自动将该export关键字编译为 module.exports = *
// es 导出
// 只能有一个,多个报错
export = function () {
console.log('default function')
}
// commonJS 引入
import defaultFunc from './xx.ts'
八,typescript单独进行类型检查(babel 不会进行类型检查)
tsc --watch // 类型检查
tsc --init // 生成配置文件