Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
Y
yifu-study-front-share
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
yifu-study
front
yifu-study-front-share
Commits
71f8eeed
Commit
71f8eeed
authored
May 23, 2022
by
刘磊
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
ssh://192.168.1.110:10022/yifu-study/front/yifu-study-front-share
parents
73cf39f2
d6296dab
Pipeline
#16116
failed with stage
Changes
1
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
208 additions
and
0 deletions
+208
-0
typeScript泛型.md
source/_posts/typeScript泛型.md
+208
-0
No files found.
source/_posts/typeScript泛型.md
0 → 100644
View file @
71f8eeed
---
title: TypeScript泛型
date: 2022/5/10 16:00:00
tags:
-
前端
-
typescript
author: 杨靖
---
## 泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
我们可以用一个函数createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:
```
typescript
function
createArray
(
length
:
number
,
value
:
any
):
Array
<
any
>
{
let
result
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
createArray
(
3
,
'x'
);
// ['x', 'x', 'x']
```
上例中,我们使用了之前提到过的数组泛型来定义返回值的类型。
这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型:
Array
<any>
允许数组的每一项都为任意类型。但是我们预期的是,数组中每一项都应该是输入的 value 的类型。
这时候,泛型就派上用场了:
```
typescript
function
createArray
<
T
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
{
let
result
:
T
[]
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
createArray
<
string
>
(
3
,
'x'
);
// ['x', 'x', 'x']
```
上例中,我们在函数名后添加了
<T>
,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array
<T>
中即可使用了。
接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:
```
typescript
function
createArray
<
T
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
{
let
result
:
T
[]
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
createArray
(
3
,
'x'
);
// ['x', 'x', 'x']
```
*定义泛型的时候,可以一次定义多个类型参数:*
```
typescript
function
swap
<
T
,
U
>
(
tuple
:
[
T
,
U
]):
[
U
,
T
]
{
return
[
tuple
[
1
],
tuple
[
0
]];
}
swap
([
7
,
'seven'
]);
// ['seven', 7]
```
上例中,我们定义了一个 swap 函数,用来交换输入的元组。
**泛型约束**
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:
```
typescript
function
loggingIdentity
<
T
>
(
arg
:
T
):
T
{
console
.
log
(
arg
.
length
);
return
arg
;
}
// index.ts(2,19): error TS2339: Property 'length' does not exist on type 'T'.
```
上例中,因为泛型 T 不一定包含属性 length,所以编译的时候报错了,是一个错误的例子。
这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:
```
typescript
interface
Lengthwise
{
length
:
number
;
}
function
loggingIdentity
<
T
extends
Lengthwise
>
(
arg
:
T
):
T
{
console
.
log
(
arg
.
length
);
return
arg
;
}
```
上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。
此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:
```
typescript
interface
Lengthwise
{
length
:
number
;
}
function
loggingIdentity
<
T
extends
Lengthwise
>
(
arg
:
T
):
T
{
console
.
log
(
arg
.
length
);
return
arg
;
}
loggingIdentity
(
7
);
// index.ts(10,17): error TS2345: Argument of type '7' is not assignable to parameter of type 'Lengthwise'.
```
多个类型参数之间也可以互相约束:
```
typescript
function
copyFields
<
T
extends
U
,
U
>
(
target
:
T
,
source
:
U
):
T
{
for
(
let
id
in
source
)
{
target
[
id
]
=
(
<
T
>
source
)[
id
];
}
return
target
;
}
let
x
=
{
a
:
1
,
b
:
2
,
c
:
3
,
d
:
4
};
copyFields
(
x
,
{
b
:
10
,
d
:
20
});
```
上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。
**泛型接口**
使用接口的方式来定义一个函数需要符合的形状:
```
typescript
interface
SearchFunc
{
(
source
:
string
,
subString
:
string
):
boolean
;
}
let
mySearch
:
SearchFunc
;
mySearch
=
function
(
source
:
string
,
subString
:
string
)
{
return
source
.
search
(
subString
)
!==
-
1
;
}
```
当然也可以使用含有泛型的接口来定义函数的形状:
```
typescript
interface
CreateArrayFunc
{
<
T
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
;
}
let
createArray
:
CreateArrayFunc
;
createArray
=
function
<
T
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
{
let
result
:
T
[]
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
createArray
(
3
,
'x'
);
// ['x', 'x', 'x']
```
```
typescript
interface
CreateArrayFunc
<
T
>
{
(
length
:
number
,
value
:
T
):
Array
<
T
>
;
}
let
createArray
:
CreateArrayFunc
<
any
>
;
createArray
=
function
<
T
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
{
let
result
:
T
[]
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
createArray
(
3
,
'x'
);
// ['x', 'x', 'x']
```
*使用泛型接口的时候,需要定义泛型的类型。*
**泛型类**
与泛型接口类似,泛型也可以用于类的类型定义中:
```
typescript
class
GenericNumber
<
T
>
{
zeroValue
:
T
;
add
:
(
x
:
T
,
y
:
T
)
=>
T
;
}
let
myGenericNumber
=
new
GenericNumber
<
number
>
();
myGenericNumber
.
zeroValue
=
0
;
myGenericNumber
.
add
=
function
(
x
,
y
)
{
return
x
+
y
;
};
```
**泛型参数的默认类型**
在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。
```
typescript
function
createArray
<
T
=
string
>
(
length
:
number
,
value
:
T
):
Array
<
T
>
{
let
result
:
T
[]
=
[];
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
result
[
i
]
=
value
;
}
return
result
;
}
```
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment