在TypeScript中定义数组有两种方式web
// 第一种方式是能够在元素类型后面接上[]
const listOne: number[] = [1, 2, 3] // 第二种方式是数组泛型,Array[元素类型] const listTwo: Array<number> = [4, 5, 6] 复制代码
类型断言分做两种形式typescript
// 第一种用 "尖括号"
const stringOne: any = 'hello TypeScript' const stringOneLength: number = (<string> stringOne).length // 第二种用 关键字 “as” const stringTwo: any = 'hello TypeScript' const stringTwoLength: number = (stringTwo as string).length 复制代码
tips: 在TypeScript的JSX中类型断言可使用as,而不容许使用尖括号方式数组
使用枚举能够清晰地表达咱们的意图,好比 订单的状态开始是0,未结帐是1,运输中是2,运输完成是3,已收货是4编辑器
使用数字枚举来完成订单的状态函数
enum OrderStatus {
START, UNPAID, SHIPPING, SHIPPED, COMPLETE } console.log( OrderStatus.START, // 0 OrderStatus.UNPAID, // 1 OrderStatus.SHIPPING, // 2 OrderStatus.SHIPPED, // 3 OrderStatus.COMPLETE, // 4 ) 复制代码
tips: 举可让咱们定义一些名字有意义的常量, 使用枚举能够清晰地表达咱们的意图ui
enum OrderStatus {
START = 'START', UNPAID = 'UNPAID', SHIPPING = 'SHIPPING', SHIPPED = 'SHIPPED', COMPLETE = 'COMPLETE' } console.log( OrderStatus.START, // START OrderStatus.UNPAID, // UNPAID OrderStatus.SHIPPING, // SHIPPING OrderStatus.SHIPPED, // SHIPPED OrderStatus.COMPLETE, // COMPLETE ) 复制代码
tips: 因为字符串枚举没有递增的含义,字符串枚举成员都必须手动初始化, 字符串枚举能进一步提高可读性,且在运行时中提供具备刻度性质的值es5
enum Test {
PRAISE } console.log( TEST.PRAISE, // 0 TEST[0] // 'PRAISE' ) // 缘由: 编译器拿到这段代码会编译到JavaScript,是以下这样的 (function (Enum) { Enum[Enum['PRAISE'] = 0] = 'PRAISE' })(Enum || (Enum = {})) 复制代码
tips: 在字符串枚举中没有反向映射spa
symbol成为一种新的原生类型,就像基本类型 number
和 string
同样设计
const symbolOne = Symbol('hello')
const symboTwo = Symbol('hello') symbolOne === symbolTwo // false 复制代码
tips: 经过一样的方式生成两个symbol,也是不一样的,由于symbol是惟一的code
泛型用于提高代码的重用性咱们但愿本身编写的代码,不管是模块仍是组件,不只能支持当前设计的数据类型,并且也能支持未来的数据类型。这在大型系统中是很是基础且重要的功能。因此咱们经常能在各类各样的静态类型语言中看到泛型设计,使得用户能够灵活地选择但愿支持的类型,而非局限于某一种类型
function hello<T>(arg:T): T {
return arg } console.log( hello('string'), hello(23), hello({name: 'Praise'}) ) // string 23 { name: 'Praise' } 复制代码
tips: 泛型变量T,T表明用户即将传入的类型。类型既能够是number,也能够是string,而在最后,咱们还使用T做为返回值的类型。这就达到了返回 值和参数类型相同的目的,保持住了函数表达的准确性
使用泛型函数 有两种方法能够选择
// 第一种 使用熟悉的尖括号方式进行表达
const optput = hello<string>('hello TypeScript') // 第二种 使用类型推断 const optput = hello('hello TypeScript') 复制代码
function hello<T>(arg: T): T {
console.log(arg.length) // error TS2339: Property 'length' does not exist on type 'T'. return arg } 复制代码
tips: 编译器会很是迅速地进行报错,告诉咱们泛型T并无length这个属性
可使用泛型数组来表达这样的状况
// 中括号 表达
function hello<T>(args: T[]): T[] { console.log(args.length) return args } // Array 表达 function hello<T>(args: Array<T>): Array<T> { console.log(args.length) return args } 复制代码
一个很经常使用的场景,好比函数传参
interface IPraise {
name: string age: number hobby: Array<string> } function person(arg: IPraise): IPraise { return arg } console.log( person({name: 'Praise', age: 23, hobby: ['code']}) ) 复制代码
将一个已知类型的每一个属性都变为可选的,好比像这样使用问号
interface IPraise {
name?: string age?: number hobby?: Array<string> } 复制代码
tips: 在实例化IPraise时,咱们没必要给每一个属性都赋值
interface IPraise {
readonly name: string readonly age: number readonly hobby: Array<string> } 复制代码
在不肯定属性数量的状况下可使用索引签名来添加一些额外的属性
interface IPraise {
name: string age: number hobby: Array<string> [propName: string]: any } 复制代码
tips: IPraise的属性值都是只读不可修改的
type NewType = number & string
let newType: NewType interface IPraiseOne { name: string age: number } interface IPraiseTwo { hobby: Array<string> } type Praise = IPraiseOne | IPraiseTwo let praise: Praise 复制代码
在映射类型里,新类型以相同的形式去转换旧类型里的每一个属性。例如,你能够令每一个属性成为只读类型或可选类型
type Readonly<T> = {
readonly [P in keyof T]: T[p] } type Partial<T> = { [P in keyof T]?: T[P] } type PersonPartial = Partial<Person> type ReadonlyPerson = Readonly<Person> 复制代码
tips: 内置的类型还有Required、Pick、Record、Exclude、Extract、NonNullable;读者能够本身尝试这些类型方法,它们的实现都在typescript/lib/lib.es5.d.ts中
// 一个Lodash中常见的pluck函数,就是从对象中选取属性的子集. 下面是pluck函数的简化版示例
function pluck(obj, names) { return names.map(name => obj[name]) } 复制代码
若是须要在TypeScript中使用这个函数,要经过索引类型查询
和索引访问
操做符:
function pluck<T, K extends keyof T>(obj: T, names: K[]): T[K][] {
return names.map(name => obj[name]) } interface Person { name: string age: number } const person: Person = { name: 'Praise', age: 23 } pluck(person, ['name']) // Praise 复制代码
tips: 编译器会检查传入的值是不是Person属性的一部分
让咱们解释一下上面代码的意义
keyof
关键字能够获取T,也就是Person的全部属性名,即['name','age']
extends
关键字让泛型K继承了Person的全部属性名,即['name','age'],依托于
keyof
关键字完成了类型索引