Skip to content

TS 函数类型

什么是函数类型

ts
// foo本身也是一个标识符,也有自己的类型
function foo(arg: number): number {
	return 123
}

const foo = (arg: number) => {
	return 123
}

函数类型表达式

ts
// 方案一: 函数类型表达式 function type expression
// 格式: (参数列表) => 返回值
type fnType = (num: number) => number

const fn: fnType = (arg: number): number => {
	return 123
}

函数类型表达式案例

ts
type FnType = (num1: number, num2: number) => number

// 2.定义一个函数
const calc = (fn: FnType) => {
	const num1 = 123
	const num2 = 321
	const res = fn(num1, num2)
	console.log(res)
}

// 3.传入值返回函数调用
const addFn = (num1: number, num2: number) => {
	return num1 + num2
}

// 2.调用函数并向函数内传入一个函数
calc(addFn)

export {}

调用签名

开发中如何选择

  1. 如果只是描述函数类型本身(函数可以被调用)使用函数类型表达式(function type expression)
  2. 如果在描述函数作为对象可以被调用,同时也可以有其他属性,使用函数调用签名
ts
// 1.函数类型表达式
type FooType = (num1: number) => number

// 2.函数的调用签名(从对象角度来看待这个函数,也可以有其他属性)
interface IFoo {
	name: string
	age: number
	// 函数可以调用: 函数调用签名
	// (参数列表):number
	(num1: number): number
}
const foo: IFoo = (num1: number): number => {
	return 123
}

foo.name = 'sj'
foo.age = 19
foo(321)

export {}

构造签名(了解)

个构造签名( Construct Signatures ),方法是在调用签名前面加一个 new 关键词

ts
class Person {}

interface ICTORPerson {
	new (): Person
}

function factory(fn: ICTORPerson) {
	return new fn()
}

factory(Person)

参数的可选类型

ts
// y就是可选参数
// 可选参数类型: number | undefined
function foo(x: number, y?: number) {
	if (y != undefined) {
		console.log(x, y + 10) // 10 30
	}
}
foo(10)
foo(10, 20)

export {}

参数的默认值

ts
// 函数的参数可以有默认值
// 1. 有默认值的情况下,参数类型可以省略
// 2. 有默认值的参数,可以接受一个undefined的值
function foo(x: number, y: number = 100) {
	console.log(x, y)
}

foo(10)
foo(10, 20)

剩余参数

从 ES6 开始,JavaScript 也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。

ts
function sum(...nums: number[]) {
	let value = 0
	for (const num of nums) {
		value += num
	}
	return value
}

const result = sum(10, 20, 30)

函数的重载(了解)

ts
// TypeScript 中函数重载写法
// 1. 先编写重载签名
function add(arg1: number, arg2: number): number
function add(arg1: string, arg2: string): string

// 2.编写通用函数实现
function add(arg1: any, arg2: any): any {
	return arg1 + arg2
}
add(10, 20)
add('aaa', 'bbb')

函数重载和联合类型选择

案例: 获取一个数据的长度(可以使用联合类型实现尽量用联合类型)

ts
// 1.函数的重载
function getLength(arg: string): number
function getLength(arg: any[]): number

function getLength(arg: any) {
	return arg.length
}
getLength('aaaaaa')
getLength(['abc', 'cba', 'nba'])

// 2.联合类型(可以使用联合类型实现尽量用联合类型)
function getLength(arg: string | any[]) {
	return arg.length
}
getLength('aaaaaa')
getLength(['abc', 'cba', 'nba'])

// 3.对象类型实现
function getLength(arg: { length: number }) {
	return arg.length
}
getLength('aaaaaa')
getLength(['abc', 'cba', 'nba'])

可推导的 this 类型

sh
# 初始化 ts 的配置文件
tsc --init

创建一个 tsconfig.json 文件,并且在其中告知 VSCodethis 必须明确执行(不能是隐式的);

在设置了 noImplicitThis 为 true 时, TypeScript 会根据上下文推导 this,但是在不能正确推导时,就会报错,需要我们明确 的指定 this。

ts
// 1.对象中的函数中的this
const obj = {
	name: 'sj',
	studying() {
		console.log(this.name)
	},
}
obj.studying()

// 2.this的指定类型
function foo(this: { name: string }, infos: { name: string }) {
	console.log(this) // { name: 'sj' }
	console.log(infos.name) // XQ
}
// 第一个参数绑定this 第二个参数是传入的参数
foo.call({ name: 'sj' }, { name: 'XQ' })

this 相关的内置工具

Typescript 提供了一些工具类型来辅助进行常见的类型转换,这些类型全局可用。

ThisParameterType:

  • 用于提取一个函数类型 Type 的 this (opens new window)参数类型;
  • 如果这个函数类型没有 this 参数返回 unknown;
ts
type FooType = typeof foo

// 1.ThisParameterType: 获取 FooType 类型中的 this 类型
type FooThisType = ThisParameterType<FooType>

function foo(this: { name: string }) {
	console.log(this.name)
}

OmitThisParameter:

  • 用于移除一个函数类型 Type 的 this 参数类型, 并且返回当前的函数类型
ts
type FooType = typeof foo

// 2.OmitThisParameter: 删除 this 参数类型,剩余的函数类型
type FooThisType = OmitThisParameter<FooType>

function foo(this: { name: string }) {
	console.log(this.name)
}

ThisType:

  • 这个类型不返回一个转换过的类型,它被用作标记一个上下文的 this 类型。
  • 事实上官方文档的不管是解释,还是案例都没有说明出来 ThisType 类型的作用
ts
// 3.ThisType: 用于绑定一个上下文的this类型
interface IState {
	name: string
	age: number
}
interface IStore {
	state: IState
	fn?: () => void
}
const store: IStore & ThisType<IState> = {
	state: {
		name: 'sj',
		age: 19,
	},
	fn: function () {
		console.log(this.name)
	},
}
store.fn?.call(store.state)

function foo(this: { name: string }) {
	console.log(this.name)
}