Skip to content

TS-02 接口定义、函数定义

一、接口

接口为类型接口,提供给变量使用类型的;

  • 生成tslint.json文件:tslint --init
  • 配置tslint文件
json
"rules": {
    "quotemark": false, // 取消双引号
    "semicolon": false, // 取消结尾分号
    "interface-name": [true, "never-prefix"], //interface接口不需要前缀
    "object-listeral-sort-keys": false, // 接口排序不按照首字母排序
}

使用interface来定义接口

定义接口使用逗号隔开、分号隔开、换行都是可以的;

js
// 对象定义接口
interface Vegetable {
    color?: string, // 可选属性
    type: string, // 必填属性
}
const getVegetable = ({color, type}: Vegetable): string => {
    return `${color ? (color + ' ') : ''}${type}`
}

// 数组定义接口
interface ArrInter {
    0: string,
    1: number
}
let arr: ArrInter = ['a',2]

任意属性

  • 使用类型断言
ts
getVegetable({
    color: 'red',
    type: 'tomato',
    size: 2
} as Vegetable) // 类型断言, 指定就是Vegetable
  • 使用[propName: string]
ts
interface Vegetable {
    color?: string,
    type: string,
    [prop: string]: any // 索引只能是string或number 属性是字符串, 值是任意类型
}

注意:如果值不是any,而是string或number,则成员都得是string或number,当然也可以使用或者;

  • 提取对象
ts
const vegetableInfo = {
    color: 'red',
    type: 'tomato',
    size: 2
}
getVegetable(vegetableInfo) // 将对象取出存变量, 里面的属性多了无所谓

只读属性

js
interface Vegetable {
    color?: string,
    readonly type: string // 只读的, 无法被修改
}
let obj: Vegetable = {type: 'tomato'}
obj.type = 'carrot' // 报错

定义函数

js
interface AddFun {
    (num1: number, num2: number): number
}

//使用
const add: AddFun = (n1, n2) => n1 + n2

索引类型 使用接口定义数组

js
interface RoleDic {
    [index: number]: string
}
const role: RoleDic = {
    0: 'admin' // 只能是数字类型的属性名, 否则报错
}

// 当指定的索引类型为string时
interface RoleDic {
    [id: string]: string
}
const role: RoleDic = {
    0: 'admin' // 数字也不会报错, 因为属性名会被调用toString转换
}

接口继承

js
interface Vegetable {
    color: string
}
interface Tomato extends Vegetable {
    radius: number
}
// Tomato接口继承了Vegetable接口, 在使用时必须传入两个参数, color和radius;

混合类型

ts3.1之前的版本需要借助命名空间,ts3.1之后的版本可以直接定义接口混合类型

js
interface Counter {
    (): void, // 返回空的函数
    count: number // 给函数添加count属性
}

// 返回的类型就是Counter,有一个函数和一个属性
const getCounter = (): Counter => {
    const c = () => {c.count++}
    c.count = 0
    return c
}

// 接收的类型就是Counter, 有函数和属性
const counter: Counter = getCounter()

总结

  1. 定义接口
js
interface Person {
    name: string,
    age?: number,
    readonly size: number, // 只读属性
    [prop: string]: any // 多余属性要写any
}
  1. 索引类型,当为string时,可以是数字和字符串,当为number时,只能是数字
  2. 当参数传入过多时,解决办法
    • 解决一:定义[prop:string]: any
    • 解决二:使用类型断言,强行指定类型
    • 解决三:定义一个变量,传入方法
  3. 接口继承:使用extends,和类相似
  4. 混合类型:在一个函数上面即有属性也有方法

二、函数

函数声明

ts
// 函数声明
function sum(x, y){
    return x + y
}

// 函数表达式
let mySum = function(x,y){
    return x + y
}

函数声明定义类型

  • 函数声明需要把输入和输出都考虑到
ts
function sum(x: number, y:number): number{
    return x + y
}
sum(1,2,3) // 多余参数报错

函数表达式

ts
// 错误的函数表达式声明
let add = function(x: number, y:number): number => {
    return arg1 + arg2
}
// 错误的声明方式add是通过类型推论出来的,下面的是正确的声明类型;

// 正确的类型声明
let add: (x:number, y: number) => number = (arg1: number, arg2: number): number => {
    return arg1 + arg2
}

let add: (x:number, y: number) => number
add = (arg1: string, arg2: number) => arg1 + arg2 // 会报错, arg1不能为string

let arg3;
add = (arg1: number, arg2: number) => arg1 + arg2 + arg3 // arg3是不需要写在参数里面的

类型别名定义函数

类型别名使用type定义

ts
// 使用别名定义函数
type Add = (x: number, y: number) => number

type isString = string // isString就是string了

可选参数

在js中,可选参数可以是在任何地方,只要使用undefined占位;

在ts中,可选参数必须是在最后面;

js
type AddFunction = (arg1: number, arg2: number, arg3?: number) => number

let addF: AddFunction
addF = (arg1:number, arg2: number) => arg1 + arg2

默认值

在定义默认值可以不需要类型判断, 因为会自动判断类型, 在传入时也不能传入字符串了

js
addF = (arg1: number, arg2 = 3) => arg1 + arg2

不确定形参个数

args为数组,因此后面的类型使用数组判断,使用...接收剩余的参数

js
const handleData = (arg1: number, ...args: number[]) => {}

函数重载

重载允许一个函数接受不同数量或类型的参数时,作不同的处理;

函数重载只能使用function来定义,不能使用接口和类型别名定义;

js
// 函数之前定义方法
function reverse(x: number | string): number[] | string[] {}
// 有一个缺点, 不能够精确的表达;

// 函数重载
function reverse(x: number): number[]
function reverse(x: string): string[]
function reverse(x: any): any {
    if(typeof x === 'string'){
        return x.split('')
    } else {
        return x.toString().split('').map((item) => Number(item))
    }
}

Released under the MIT License.