学习 TS 有一段时间了,目前很多的一些项目都开始往 TS 转,在写的过程中总会遇到一些大大小小的问题,然后也没人一起学习与帮助,还是蛮吃力的。
所以将在整体的学习过程中,我认为比较重要的点都在这记录下来,以后遇到的一些问题都会往这里补充吧,如果大家有想一起分享的,都可以写在评论区,然后我再补充到文章中,咱们社区也能建立起好的前段氛围呀
函数剩余参数的类型定义
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
函数中重载的类型定义
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
# 输入 number 出 number,输入 string 出 string,但是上面显然不能满足
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
类型断言
#1. 值 as 类型
#2. <类型>值
# 作用1:确定联合类型中的类型
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function getName(animal: Cat | Fish) {
return animal.name;
}
function isFish(animal: Cat | Fish) {
# 这里会报错的
if (typeof animal.swim === 'function') {
return true;
}
return false;
}
----- 需要了解返回的是那个类型
function isFish(animal: Cat | Fish) {
# 利用 as 表示此时的 animal 为 Fish 类型
if (typeof (animal as Fish).swim === 'function') {
return true;
}
return false;
}
双重断言
- 任何类型可以被断言为 any
- any 可以被断言为任何类型
所以可以利用 as any as Foo
将任何一个类型断言为另一个类型
interface Cat {
run(): void;
}
interface Fish {
swim(): void;
}
function testCat(cat: Cat) {
return (cat as any as Fish);
}
# 当然使用双重断言是非常不友好的,除非迫不得已,尽量别使用
类型断言解决泛型
function getCacheData(key: string): any {
return (window as any).cache[key];
}
interface Cat {
name: string;
run(): void;
}
const tom = getCacheData('tom') as Cat;
tom.run();
---- 类型断言去掉 any
function getCacheData<T>(key: string): T {
return (window as any).cache[key];
}
interface Cat {
name: string;
run(): void;
}
const tom = getCacheData<Cat>('tom');
tom.run();
字符串约束取值
有时候,比如某个参数只能是 a 或者 b 的时候
# 首先可以这么写
let func = (str: 'top' | 'end') => {}
# 同时也可以字符串字面量类型
# 字符串字面量类型用来约束取值只能是某几个字符串中的一个。
type Flow = 'top' | 'end'
let func = (str: Flow) => {}
# 还可以使用类型别名
type Flow = {
top: string,
end: string
}
let func = (str: keyof Flow) => {}
元组与数组泛型的联合类型
元素可以确定数据类型,但是不能超过范围,可以理解元组可以固定数组长度,超出范围并不能保证其类型。
# 基本定义
let tom: [string, number];
tom = ['Tom', 25];
tom.push('male');
tom.push(true); // Argument of type 'true' is not assignable to parameter of type 'string | number'.
# 数组泛型与元组的去呗
type Name = string|number
let arr: Array<Name> = ['Tom', 25]
arr = [25, 'Tom']
let tom: [string, number];
tom = ['Tom', 25]; // true
tom = [25, 'Tom'] // false Type 'string' is not assignable to type 'number'.(2322)
快速生成一个 ts 模板库
npm install -g tsdx
命名空间的作用( namespace
)
类似于闭包的作用(立即执行函数):作用域的另一种抽象,为了防止相同名称带来的冲突。
// 命名空间
namespace Utility {
export const log = (msg:string) => console.log(msg)
export const error = (msg:string) => console.error(msg)
}
Utility.log('hello')
Utility.error('error')
箭头函数泛型怎么写
# <T> 不写 reverse<T> 而是 reverse = <T>()=>{}
const reverse = <T>(items: T[]): T[] => {
let toreturn = []
for(let i = items.length - 1; i>=0; --i) {
toreturn.push(items[i])
}
return toreturn
}
const sample = [1, 2, 3]
let reversed = reverse(sample)
console.log(reversed)
const strs = ['b', 'a', 'c']
let reversed1 = reverse<string>(strs)
console.log(reversed1)
交叉类型怎么写
比如需要将两个对象进行合并,这时候需要使用交叉类型,类似于 Java 一样的交叉类型
const extend = <T extends object, U extends object>(a:T, b:U):T&U=> {
const result = <T&U>{}
for(let id in a) {
// 注意这里需要加上 <T>
(<T>result)[id] = a[id]
}
for(let id in b) {
// 注意这里需要加上 <T>
if(result.hasOwnProperty(id)) (<U>result)[id] = b[id]
}
return result
}
const x = extend({a:'hello'}, {a:1,b:42})
类型不存在怎么办
比如 Window 之类的都是存在,加入某个公共的类不存在怎么办呢,可以创建一个 global.d.ts
声明一些需要的类型。
重载解决可选参数声明
function padding(a: number, b?: number, c?: number, d?: any) {
if (b === undefined && c === undefined && d === undefined) {
b = c = d = a;
} else if (c === undefined && d === undefined) {
c = a;
d = b;
}
return {
top: a,
right: b,
bottom: c,
left: d
};
}
# -------
// 重载
function padding(all: number):any;
function padding(topAndBottom: number, leftAndRight: number):any;
function padding(top: number, right: number, bottom: number, left: number):any;
// Actual implementation that is a true representation of all the cases the function body needs to handle
function padding(a: number, b?: number, c?: number, d?: number) {
if (b === undefined && c === undefined && d === undefined) {
b = c = d = a;
} else if (c === undefined && d === undefined) {
c = a;
d = b;
}
return {
top: a,
right: b,
bottom: c,
left: d
};
}
padding(1); // Okay: all
padding(1, 1); // Okay: topAndBottom, leftAndRight
padding(1, 1, 1, 1); // Okay: top, right, bottom, left
padding(1, 1, 1); // Error: Not a part of the available overloads
nerver 与 void
- void 表示的是返回为空(undefined),实际上是有返回值的
- never 是一个不包含值的类型,这意味着具有这种返回类型的函数永远不能正常返回。这意味着要么抛出异常,要么无法终止。
# void returns void, never never returns.
function do(): never {
while (true) {}
}
const error = (msg) => throw new Error(msg); // never
const fail = () => error('failed here.'); // never
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于