TypeScript LeetCode 面试题 All In One
TypeScript LeetCode 面试题 All In One
TypeScript In Action
TypeScript 复杂类型
编写复杂的 TypeScript 类型
// 方法「只可能」有两种类型签名
interface Action<T> {
payload?: T
type: string
}
asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>
syncMethod<T, U>(action: Action<T>): Action<U>
interface Action<T> {
payload?: T;
type: string;
}
// 还可能有一些任意的「非函数属性」
class EffectModule {
count = 1;
message = "hello!";
delay(input: Promise<number>) {
return input.then((i) => ({
payload: `hello ${i}!`,
type: "delay",
}));
}
setMessage(action: Action<Date>) {
return {
payload: action.payload!.getMilliseconds(),
type: "set-message",
};
}
}
// 现在有一个叫 connect 的函数,它接受 EffectModule 实例,将它变成另一个对象,
// 这个对象上只有「EffectModule 的同名方法」,但是方法的类型签名被改变了
asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>
// 变成了
asyncMethod<T, U>(input: T): Action<U>
syncMethod<T, U>(action: Action<T>): Action<U>
// 变成了
syncMethod<T, U>(action: T): Action<U>
demo
interface Action<T> {
payload?: T;
type: string;
}
class EffectModule {
count = 1;
message = "hello!";
delay(input: Promise<number>) {
return input.then((i) => ({
payload: `hello ${i}!`,
type: "delay",
}));
}
setMessage(action: Action<Date>) {
return {
payload: action.payload!.getMilliseconds(),
type: "set-message",
};
}
}
type Connected = {
delay(input: number): Action<string>;
setMessage(action: Date): Action<number>;
};
const effectModule = new EffectModule();
const connected: Connected = connect(effectModule);
要求:
在题目链接[1] 里面的 index.ts 文件中,
有一个 type Connect = (module: EffectModule) => any,将 any 替换成题目的解答,让编译能够顺利通过,
并且 index.ts 中 connected 的类型与 Connected「完全匹配」
type Connected = {
delay(input: number): Action<string>;
setMessage(action: Date): Action<number>;
};
https://github.com/LeetCode-OpenSource/hire/blob/master/foundations-zh/src/index.ts
export interface ErrorMessage {
message: string
stack: Array<{
line: number
column: number
filename: string
}>
}
export function parseError(err: Error): ErrorMessage {
// implement
}
solution
import { expect } from "chai";
interface Action<T> {
payload?: T;
type: string;
}
class EffectModule {
count = 1;
message = "hello!";
delay(input: Promise<number>) {
return input.then((i) => ({
payload: `hello ${i}!`,
type: "delay"
}));
}
setMessage(action: Action<Date>) {
return {
payload: action.payload!.getMilliseconds(),
type: "set-message"
};
}
}
// 修改 Connect 的类型,让 connected 的类型变成预期的类型
// type Connect = (module: EffectModule) => any;
// 1. 过滤出成员属性的函数 ✅
type FilterFunction<Obj> = {
// 仅仅过滤 Function
[K in keyof Obj]: Obj[K] extends Function ? K : never;
}[keyof Obj];
type Connect = (
module: EffectModule
) => {
// 2. 使用 infer 动态获取 参数类型
[K in FilterFunction<EffectModule>]: EffectModule[K] extends (
input: Promise<infer T>
) => Promise<Action<infer U>>
? (input: T) => Action<U>
: EffectModule[K] extends (action: Action<infer T>) => Action<infer U>
? (action: T) => Action<U>
: never;
// 👎 input & action 形参必须写死 ???
};
/*
type Connect = (module: EffectModule) => {
delay: (input: number) => Action<string>;
setMessage: (action: Date) => Action<number>;
}
*/
const connect: Connect = (module) => ({
delay: (input: number) => ({
type: "delay",
payload: `hello 2`
}),
setMessage: (input: Date) => ({
type: "set-message",
payload: input.getMilliseconds()
})
});
type Connected = {
delay(input: number): Action<string>;
setMessage(action: Date): Action<number>;
};
export const test = connect(new EffectModule());
/*
type Connect = (module: EffectModule) => {
delay: (input: number) => Action<string>;
setMessage: (action: Date) => Action<number>;
}
*/
export const connected: Connected = connect(new EffectModule());
refs
LeetCode 面试题
https://github.com/LeetCode-OpenSource/hire
https://mp.weixin.qq.com/s/dWF9bPd9QhgsnuAHX33bNQ
https://github.com/LeetCode-OpenSource/hire/blob/master/foundations_zh.md
https://github.com/LeetCode-OpenSource/hire/blob/master/typescript_zh.md
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/13611172.html
未经授权禁止转载,违者必究!