Skip to content

Instantly share code, notes, and snippets.

@teal-front
Last active August 18, 2022 03:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teal-front/235165300d3a5e0edd4c1fabf3750a9f to your computer and use it in GitHub Desktop.
Save teal-front/235165300d3a5e0edd4c1fabf3750a9f to your computer and use it in GitHub Desktop.
TS-高级用法
// region Unknown vs. any
// unknown: unknown provide safer typing,
// you should use type assertion or narrow to a special type
// if you want to perform operations on unknown.
function f1(a: any) {
a(); // OK
}
function invokeAnything(callback: unknown) {
if (typeof callback === 'function') {
callback();
}
}
invokeAnything(1);
//
function isNumberArray(value: unknown): value is number[] {
// if (Array.isArray(value)) {
return Array.isArray(value) && value.every(element => typeof element === "number")
// }
// return false
}
const unknownValue: unknown = [15, 23, 8, 4, 42, 16];
if (isNumberArray(unknownValue)) {
// Within this branch, `unknownValue` has type `number[]`,
// so we can spread the numbers as arguments to `Math.max`
const max = Math.max(...unknownValue);
console.log(max);
}
// endregion
/// region 泛型约束
function longest<T extends { length: number }>(a: T, b: T) {
return a.length > b.length ? a : b;
}
longest('123', '12');
longest(1, 2);
// 获取promise的返回值
type UnpickPromise<T extends Promise<any>> = T extends Promise<infer P> ? P : never
type PromiseValue = UnpickPromise<Promise<Promise<number>>>
const v = axios.get('')
.then(res => res.data)
.then(data => {
console.log(data)
})
const num: PromiseValue = '1'
type PromiseValue1 = UnpickPromise<object>
/// endregion
/// region 条件类型(Conditional Types) & Infer
// https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#conditional-type-constraints
// https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types
// 一般条件类型
type IsElementArray<T> = T extends any[] ? true : false;
type V1 = IsElementArray<[3, 4]>
type V2 = IsElementArray<string>
// 带infer的条件类型
type ParamType2<T, P extends any[]> = T extends (...args: P) => any ? P : T;
type V32 = ParamType<(a: number, b: string) => void, [number, string]>
type ParamType<T> = T extends
(...args: infer P) => any // function type
? P
: never;
type MyReturnType<T> = T extends (...args) => infer P ? P : never;
type V3 = ParamType<(a: number, b: string) => void>
type V22 = ParamType<number>
type MyReturnValue = ReturnType<(a: number, b: string) => object>
type Reducer<S, A extends any> = (prevState: S, action: A) => S
type Reducer1 = (prevState, action) => any
const reducer: Reducer<string, () => number> = (prevState, action) => {
return prevState.toNumber()
}
// 获取reducer的state
type ReducerState<R extends Reducer<any, number>> = R extends Reducer<infer S, string> ? S : never
type State = ReducerState<Reducer<string, number>>
// 获取reducer的action
type ReducerAction<R extends Reducer<any, any>> =
R extends Reducer<any, infer A> ? A : never
/// endregion
/// region 类型保护
// https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#defining-a-union-type
function welcomePeople(x: string[] | string) {
// x: string[] | string
// console.log("Hello, " + x.join(" and "));
if (Array.isArray(x)) {
// Here: 'x' is 'string[]'
console.log("Hello, " + x.join(" and "));
} else {
// Here: 'x' is 'string'
console.log("Hello, " + x.join(" and "));
console.log("Welcome lone traveler " + x);
}
}
/// endregion
/// region 类型扩展
// interface extends
interface Colorful {
color: string
}
interface Square extends Colorful{
// color: number
color: string
sideLength: number
}
// intersection type
type Circle = {
color: number
radius: number
}
type ColorfulSquare = Circle & Colorful
type Color = ColorfulSquare['color']
/// endregion
/// region 类型预测(type predicates)
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
interface Person {
name: string;
}
interface House {
address: string;
}
const values: (Person | House)[] = [
{ name: "Kim" },
{ address: "123 street" },
];
function isPerson(value: Person | House): value is Person{
// return (value as Person).name !== undefined;
return false
}
function isHouse(value: Person | House | string): value is House {
return (value as House).address !== undefined;
}
for (const v of values) {
// v is `Person | House | string`
if (isPerson(v)) {
// v is `Person`
console.log(v.name);
v.address
} else{
console.log(v.name);
v.address
// v is `House`
}
// v is `Person | House | string`
}
/**
* 使用注意事项: parameter is Type
* 如果函数返回的是true,则parameter被认为是Type类型,否则不是
*/
// 在箭头函数中的使用
values
.filter((v): v is Person => (v as Person).name !== undefined)
.forEach((v) => {
// v is `Person`
});
// endregion
/// region 类型体操
/**
* 类型体操,社区的称呼
* TypeScript 高级类型是通过 type 定义的有类型参数(也叫泛型)的类型,它会对传入的类型参数做一系列的类型计算,产生新的类型
* 这个过程会涉及一系列的类型计算逻辑,这些类型计算逻辑就叫做类型体操。
*/
// 高级类型
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
};
// 去除数组第一个元素
type Shift<T extends unknown[]> = T extends [infer R, ...infer Rest] ? [...Rest] : never;
// trim string(使用了递归)
type TrimLeft<Str extends string> = Str extends `${' ' | '\t' | '\n'}${infer Rest}` ? TrimLeft<Rest> : Str;
type TrimRight<Str extends string> = Str extends `${infer Rest}${' ' | '\t' | '\n'}` ? TrimRight<Rest> : Str;
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;
type S = Trim<string>
const s = ' sdiods' as S;
function trim<T extends string>(s:T): Trim<s> {
}
// endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment