Skip to content

TypeScript 常见类型定义方法

1. 函数类型

1.1 函数类型表达式

函数类型表达式(Function Type Expressions)是声明函数的简单有效的方法,例如 (s: string) => string

ts
function 
greeter
(
fn
: (
s
: string) => string) {
fn
("Hello, World")
}

1.2 函数调用签名

可以声明函数的调用签名(Call Signatures)来声明函数类型。

ts
type 
Func
= {
(
s
: string): boolean
description
: string
} function
greeter
(
fn
:
Func
) {
fn
("Hello, World")
console
.
log
(
fn
.
description
)
}

Func 也常常使用 interface 来声明。

ts
interface Func {
  (
s
: string): boolean
description
: string
}

1.3 函数构造签名

如果函数需要支持 new,则需要使用 new 签名。

ts
interface Func {
  (
s
: string): boolean
new (
s
: string): Func
} function
greeter
(
fn
: Func) {
fn
("Hello, World")
return new
fn
("Hello, World")
}

new 签名和调用签名可以同时存在。

1.4 函数重载

函数重载声明也比较简单:

ts
function 
makeDate
(
timestamp
: number): Date
function
makeDate
(
m
: number,
d
: number,
y
: number): Date
function
makeDate
(
mOrTimestamp
: number,
d
?: number,
y
?: number): Date {
if (
d
!==
undefined
&&
y
!==
undefined
) {
return new
Date
(
y
,
mOrTimestamp
,
d
)
} else { return new
Date
(
mOrTimestamp
)
} }

1.5 泛型函数

最简单的泛型函数:

ts
function 
firstElement
<
T
>(
arr
:
T
[]):
T
| undefined {
return
arr
[0]
}

也可以有多个参数:

ts
function 
map
<
Input
,
Output
>(
arr
:
Input
[],
func
: (
arg
:
Input
) =>
Output
):
Output
[] {
return
arr
.
map
(
func
)
}

泛型也可以像 Java 一样有约束类型:

ts
function 
longest
<
Type
extends {
length
: number }>(
a
:
Type
,
b
:
Type
) {
if (
a
.
length
>=
b
.
length
) {
return
a
} else { return
b
} }

1.6 箭头函数

箭头函数的类型声明:

ts
let 
greet
: (
name
: string) => string
greet
= (
name
: string) => `Hello, ${
name
}`

箭头函数也可以标记返回值和泛型参数:

ts
const 
greet
= <
T
>(
name
:
T
): string => `Hello, ${
name
}`

2. 编写声明文件

2.1 描述全局命名空间

命名空间用于解决命名冲突问题,尽量在项目中避免使用命名空间,它很难去识别组件之间的依赖关系,但是在声明文件中,可以使用命名空间来描述一些全局变量。

ts
declare namespace myLib {
  function 
makeGreeting
(
s
: string): string
let
numberOfGreetings
: number
}

命名空间类似于类中大量包裹无关静态函数的做法,但是后者应该禁止使用的,因为这会导致 JavaScript 打包器中的许多优化失效(例如摇树优化 Tree Shaking)。

ts
class 
myLib
{
static
makeGreeting
(
s
: string): string
// 虽然项目中没有调用 hello() 方法,但是打包器无法知道这一点 static
hello
(): string
static
numberOfGreetings
: number
}

建议:

ts
export function 
makeGreeting
(
s
: string): string {
// ... } // 此时打包器可以知道 hello() 方法没有被调用,可以进行优化 export function
hello
(): string {
// ... }

2.2 声明全局变量

使用 declare 关键字声明全局变量:

ts
declare let 
myGlobal
: string
declare const
myConstant
: string
declare function
myFunction
(
a
: number): string

如果要在项目中声明全局变量,可以使用 declare global 关键字:

ts
type 
Observable
<
T
> = {
subscribe
(
observer
: (
value
:
T
) => void): void
} declare global { interface
Array
<
T
> {
toObservable
():
Observable
<
T
>
} } export {}

注意一定要在文件末尾加上 export {},否则不会生效。

例如,定义 process.env,创建 env.node.d.ts

ts
declare global {
  namespace NodeJS {
    interface 
ProcessEnv
{
NODE_ENV
: 'development' | 'production'
PORT
: string
} } } export {}
实例:同时定义前端和后端环境变量

在 Nuxt 3 项目中,前端可通过 import.meta.env 读取公开的环境变量,后端可通过 process.env 读取系统全部环境变量,可以同时定义两者:

ts
interface ImportMetaEnv {
  /**
   * 应用名称
   */
  readonly 
NUXT_APP_NAME
?: string
/** * 鉴权服务地址 */ readonly
NUXT_AUTH_ORIGIN
?: string
} interface ImportMeta { readonly
env
: ImportMetaEnv
} declare global { namespace NodeJS { interface
ProcessEnv
extends ImportMetaEnv {
/** * MongoDB 连接地址 */
DATABASE_URL
?: string
/** * Redis 连接地址 */
REDIS_URL
?: string
} } } export {}