一、深入对象语法
- 普通声明
// 方式一
type Person = {
name: string
}
interface Person {
name: string
}
// 方式二:索引签名 Index Signature
type Hash = {
[k: string]: unknown,
length: number
}
type List = {
[k: string]: unknown,
length: number
}
// 方式三:映射类型 Mapped Type,映射类型不能声明属性和方法,多用于泛型
type Hash = {
[k in string]: unknown
}
- 可选 key 声明
interface InputProps {
defaultvalue?: string,
value?: boolean,
onChange?: () => void
}
- readonly(只读)使用
interface User {
readonly id: number,
readonly name: number,
readonly scores: number[],
age?: number
}
二、深入函数语法,声明对象的语法都可以声明函数
- js 中声明函数的三种方式
// 方式一:普通函数
function f1(a) {
return a + 1
}
// 方式二:函数表达式
const f2 = function (a) {
return a + 1
}
// 方式三:箭头函数
const f3 = (a) => {
return a + 1
}
- ts 中声明函数的方式
// 普通函数
function f1(a: number): number {
return a + 1
}
// 函数表达式
// 1 在左边声明类型(推荐)
type F2 = (a: number) => number
const f2: F2 = function (a) {
return a + 1
}
// 2 在右边声明类型
const f3 = function (a: number): number {
return a + 1
}
// 箭头函数
// 1. 在左边声明类型(推荐)
type F4 = (a: number) => number
const f4: F4 = (a) => {
return a +1
}
// 2. 在右边声明类型
const f5 = (a: number): number => {
return a + 1
}
三、两种特殊的函数
- 构造函数(先不写)
- 类型谓词 is--用处:判断参数类型
// 判断参数类型
// 1 普通参数
type F1 = (s: string | string[]) => void
const f1: F1 = (s) => {
if (s instanceof Array) {
s.slice(0, 1)
} else {
s.split('')
}
}
// 2 非 js 类型的参数
type Person = {
name: string
}
type Animal = {}
type F2 = (p: Person | Animal) => void
// 这里使用普通函数来声明,不要使用箭头函数(箭头函数可能会有问题 )
function isPerson(p: Person | Animal): p is Person {
return 'name' in p
}
const f2: F2 = function (p) {
if (isPerson(p)) {
p // Person
} else {
p // Animal
}
}
四、函数柯里化
// const createAdd = (a: number) => {
// return (b: number) => {
// return a + b
// }
// }
// 等价于
const createAdd = (a: number) => (b: number) => a + b
// 声明类型
type CreateAdd = (a: number) => (b: number) => number
const createAdd2: CreateAdd = a => b => a + b
五、函数重载
含义:当参数类型不同 | 函数参数个数不同 | 都不同 的同名函数就叫函数重载
// 前面声明同名,最后写函数体
function getDate(t: number): Date
function getDate(y: number, m:number, d:number): Date
function getDate(a: number, b?: number, c?:number): Date {
if (a !== undefined && b === undefined && c === undefined) {
return new Date(a)
} else if (a !== undefined && b !== undefined && c !== undefined) {
return new Date(a, b, c)
} else {
throw new Error('参数非法')
}
}
getDate(10000000)
getDate(1996, 10, 7)
六、指定 this 的类型
四种方式:构造对象、call、apply、bind
type Person = {
name: string
}
function f(this: Person, word: string): void {
console.log(this.name + ' ' + word)
}
// 方式一:构造对象
const p1: Person & { f: typeof f } = {
name: 'rourou1', f
}
// 不可以直接将 p 传进去,会报应有 1 个参数,但获得 2 个的错误
// f(p, 'sayHi')
p1.f('sayHi')
// 方式二:f.call()
const p2: Person = {
name: 'rourou2'
}
f.call(p2, 'sayHi')
// 方式三:f.apply()
const p3: Person = {
name: 'rourou3'
}
f.apply(p3, ['sayHi'])
// 方式四:f.bind()
const p4: Person = {
name: 'rourou4'
}
f.bind(p4)('saiHi')
七、剩余参数,必须是函数的最后一个参数
function sum(...array: number[]): number {
return array.reduce((p, c) => p + c, 0)
}
sum(1, 2, 3)
sum(1, 1, 1, 1, 1)
八、展开参数
function f(...array: number[]): void {
console.log(array)
}
// 剩余参数
function sum(...array: number[]): number {
// 展开参数
f(...array)
return array.reduce((p, c) => p + c, 0)
}
九、as const
含义:将变量变为常量,通常用于数组/对象中(因为在js中,一个数组就算是const,也可以通过push方法改变数组)
function sum(a: number, b: number): number {
return a + b
}
// const arr = [1, 2] 并不是严格意义上的常量
const arr = [1, 2] as const // 即 arr 为 readonly
sum(...arr)
十、大融合
type Config = {
url: string,
method: 'GET' | 'POST' | 'PATCH' | 'DELETE',
data?: unknown,
headers?: unknown
}
// 参数解构&设置默认值
// 方式一:类型在 = 左边声明
function ajax1({ url, method, ...rest }: Config = { method: 'GET', url: '' }): void {
console.log(url, method, data, headers)
}
// 方式二:类型在 = 右边声明(即断言)
function ajax2({ url, method, ...rest } = { method: 'GET', url: '' } as Config): void {
console.log(url, method, data, headers)
}