@juln/type-fest
简体中文 | English
经过类型测试 的 TypeScript 类型的集合
基于 type-fest
进行二次开发,且暴露出 type-fest
提供的所有类型 (type-fest
的使用文档请自行去官方看,这里不提供)
编写类型编程指南:
- 类型编程最主要的就是,明确知道最基础的那些操作,哪些是联合转联合、哪些是联合转交叉、哪些是交叉转交叉、哪些是不可逆操作。
- 然后剩下的就是逻辑拆分,拆分成各个类型函数,再组装起来,就 OK 了。
true -> false; false -> true
type False = Negate<true>; // false
type True = Negate<false>; // true
(void extends T) and (T extends void)
(undefined extends T) and (T extends undefined)
(object extends T) and (T extends object)
filter out never
and void
将非 promise 的函数返回值变成 promise
type OriginalFn = (a: 1, b: 2) => number;
type Fn = PromiseFn<OriginalFn>; // (a: 1, b: 2) => Promise<number>
将非 promise 的函数返回值变成 promisable
type OriginalFn = (a: 1, b: 2) => number;
type Fn = PromisableFn<OriginalFn>; // (a: 1, b: 2) => Promise<number> | number
type OriginalArr = [1, ''];
type Arr = ReadonlyArray<OriginalArr>; // readonly [1, '']
type Obj = {
a: 1;
b: 2;
c: 3;
};
type ObjIsSpreadable = Obj extends Spreadable ? true : false; // true
递归获取可扩展类型的所有键。
type Obj = {
0: string;
a: {
b: {
c: string;
d: string;
};
};
e: string;
f: string;
[Symbol.hasInstance]: 0;
};
type Keys = DeepKeysOfSpreadable<Obj>; // `Keys` 等价于 0 | 'c' | 'd' | 'f' | Symbol.hasInstance;
合并多个对象
type O1 = {
a: 'a';
c: 'c';
d: {
d1: 0;
};
e: 'e';
f: 'f1';
};
type O2 = {
b: 'b';
c: 'c';
d: {
d2: 1;
};
e: { e: 'e'; };
f: 'f2';
};
type Res = MergeObjects<[O1, O2, ...]>; // { a?: 'a'; b?: 'b'; c: 'c'; d: { d1?: 0; d2?: 1; }; e: 'e' | { e: 'e'; }; f: 'f1' | 'f2'; };
合并多个对象. 具体看 MergeObjects
type Res = MergeObjects<O1 | O2>;
过滤掉 never
和 void
type OriginalArr = [1, '', false, number, string, boolean, symbol, {}, object, Error, null, undefined, never, void];
type Arr = PureArray<OriginalArr>; // [1, "", false, number, string, boolean, symbol, {}, object, Error, null, undefined]
type ReadonlyOriginalArr = readonly [1, 2, never, void];
type ReadonlyArr = PureArray<ReadonlyOriginalArr>; // readonly [1, 2]
Union 转 tuple, 但是tuple的顺序不可靠, 有可能是 [X, Y] 也可能是 [Y, X]
type abc = 'a' | 'b' | 'c';
type t = TuplifyUnion<abc>; // ["a", "b", "c"]
校验16进制颜色值
type Res1 = HexColor<'#fff'> // '#fff';
type Res2 = HexColor<'#ffffff'> // '#ffffff';
type Res3 = HexColor<'#xxx'> // never;
针对第三方库进行 ts 类型的加强
import { RPC } from "@mixer/postmessage-rpc";
import type { TypedRPC } from "@juln/type-fest";
/**
* 只能用type, 不能用interface, 不然类型约束不严格会有问题
* type ExposeMap = {
* "exposeName1": {
* isPromise: true;
* params: any;
* data: any;
* };
* "exposeName2": {
* isPromise: true;
* params: any;
* data: any;
* };
* ...
* }
*/
type ExposeMap = {
'load-error': {
data: Error;
};
'close-window': {};
'result': {
isPromise: true;
params: {
pageNum?: number;
pageSize?: number;
};
data: {
code: number;
list: any[];
};
};
}
/**
* 与ExposeMap用法一致
*/
type CallMap = {
'simpleLoad': {};
'load': {
params: {
immediately?: boolean;
};
data: {
success: boolean;
};
};
'close-modal': {};
}
const rpc: TypedRPC<ExposeMap, CallMap> = new RPC({
target: window.top!,
serviceId: "test",
});
rpc.call("close-modal", {}); // eventName, params, returnType等类型限制
rpc.call("unknown", {}); // 未声明eventName, 类型报错
// 2. 非严格模式下, 未声明的eventName, 类型不报错, handler为: (params: any) => Promise<any> | any)
(rpc as TypedRPC<ExposeMap, CallMap, false>).expose('unkown', a => a);
import { EventEmitter } from "eventEmitter3";
import type { TypedEventEmitter } from "@juln/type-fest";
/**
* interface MyEventMap {
* "eventName1": {
* args: [arg1: any, arg2: any, ...];
* };
* "eventName2": {
* args: [arg1: any, arg2: any, ...];
* };
* ...
* }
*/
interface MyEventMap {
'load-error': {
args: [Error];
};
'close': {
};
'result': {
args: [
result1: number,
result2: string,
result3: null,
];
};
}
const ee = new EventEmitter();
ee.emit('close');