num 값에 따라 함수 타입 설정하기
const Test = (type: Enum, func: any) => { ... }
일 때 Enum 값에 따라 func의 타입이 달라지는 경우가 있다. 물론 작업자가 나 혼자면 any로 써도 큰 문제는 없겠으나 여러사람과 협업할 때는 func의 타입을 부여하는게 훨씬 좋지 않을까?
export abstract class Hookable<G> {
protected _handlers: Map<any, any[]> = new Map();
public connect<T extends keyof G>(
type: T,
...options: 여기를 어떻게 해야 할까?
): void {
if (!this._handlers.has(type)) {
this._handlers.set(type, []);
}
options.forEach((f: G[T]) => this._handlers.get(type)?.push(f));
}
public disconnect<T extends keyof G>(
type: T,
...options: 여기를 어떻게 해야 할까?
): void {
const funcs = this._handlers.get(type);
if (funcs) {
options.forEach((g: G[T]) => {
funcs.filter((f: G[T]) => f === g);
});
}
}
protected abstract _emitHook<T extends keyof G>(
type: T,
sender?: any,
args?: any
): void;
public disconnectAll(): void {
this._handlers.clear();
}
}
위 클래스를 상속받아서 어떤 클래스를 구현하면 그 클래스는 Hookable 하게 된다. ( pub/sub )
여기서 핵심적으로 생각해 봐야 할 부분은 connect, disconnect 함수에 어떻게 타입을 지정하느냐다.
export type ConditionalOptions<T, K extends keyof T> = T[K] extends null
? []
: [T[K]];
위의 타입을 보자. 제네릭이라 좀 복잡할수도 있는데 하나씩 뜯어보면 심플하다. 말로 풀어서 보면
K는 T의 key이고 T[k](인덱스 타입)이 null 이면 [] null이 아니면 [T[K]]
이다. 이 인터페이스를 options의 타입으로 지정하면 된다. 이제 왜 ...options인지 받아들일 수 있다.
export abstract class Hookable<G> {
protected _handlers: Map<any, any[]> = new Map();
public connect<T extends keyof G>(
type: T,
...options: ConditionalOptions<G, T>
): void {
if (!this._handlers.has(type)) {
this._handlers.set(type, []);
}
options.forEach((f: G[T]) => this._handlers.get(type)?.push(f));
}
public disconnect<T extends keyof G>(
type: T,
...options: ConditionalOptions<G, T>
): void {
const funcs = this._handlers.get(type);
if (funcs) {
options.forEach((g: G[T]) => {
funcs.filter((f: G[T]) => f === g);
});
}
}
protected abstract _emitHook<T extends keyof G>(
type: T,
sender?: any,
args?: any
): void;
public disconnectAll(): void {
this._handlers.clear();
}
}
그럼 이제 G는 뭐고 T는 뭐로 해주면 좋겠느냐 만 남았다. 아래 코드를 보자
export enum HookType {
INITIALIZE = 'initialize',
TEST = 'test'
}
export type initializeHookFunction = (data: any) => void;
export type testHookFunction = (data: any) => number;
export interface PossibleValues {
initialize: initializeHookFunction;
test: testHookFunction;
}
PossibleValues가 G 이고 HookType의 enum 값들이 T인 것을 알 수 있다.(반드시 PossibleValues에 포함된 키만을 허용한다) 이 두개를 가지고 PossibleValues interface에서 인덱스 타입을 가져와 ~HookFunction을 추천해 준다.
생각보다 이런 케이스가 더러 있으니 알아두면 좋을 것 같다.
Author And Source
이 문제에 관하여(num 값에 따라 함수 타입 설정하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cfop/typescript-enum-값에-따라-함수-타입-설정하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)