Last active
August 18, 2022 03:40
-
-
Save teal-front/235165300d3a5e0edd4c1fabf3750a9f to your computer and use it in GitHub Desktop.
TS-高级用法
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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