IT이야기

타이프 스크립트에 필요한 매개 변수(선택 사항)

cyworld 2022. 7. 3. 10:02
반응형

타이프 스크립트에 필요한 매개 변수(선택 사항)

플럭스 실장(구체적으로는 Vuex)을 강하게 타이핑하려고 합니다.현재 코드는 다음과 같습니다.

const actions = {
  first(context: Context, payload: string) { return doSomething(context, payload); },
  second(context: Context) { return doSomethingWithNoPayload(context); }
}

type Actions = typeof actions;
type PayloadType<A extends keyof Actions> = Parameters<Actions[A]>[1];

function dispatch<A extends keyof Actions>(action: A): ReturnType<Actions[A]>;
function dispatch<A extends keyof Actions>(action: A, payload: Payload<A>): ReturnType<Actions[A]>;
function dispatch<A extends keyof Actions>(action: A, payload: Payload<A> = undefined): Promise<any> {
  return Promise.resolve({ action, payload });
}

제가 달성하려는 것은 다음과 같습니다.

dispatch("first") // error, no payload specified
dispatch("first", false) // error, payload type is not correct
dispatch("first", "correct") // ok, payload type is correct

dispatch("second", "something") // error, shouldn't pass payload`
dispatch("second") // ok, payload is not passed
dispatch("third") // error, non-existent action

그러나 옵션 파라미터를 payload로 사용한다고 해서 실제로 payload가 필요한 "first" 액션에 payload를 전달하도록 강제되는 것은 아닙니다.payload를 옵션이라고 선언하지 않으면 강제로 전화를 걸어야 합니다.dispatch("second", undefined)두 개의 매개 변수를 통과해야 하니까

무슨 생각 있어?대단히 감사합니다.

컴파일러가 필요한 경우를 가정하여 다음과 같이 진행하겠습니다.dispatch()유형에서 프로그래밍 방식으로 서명하다actions우선, 예를 컴파일 하기 위해서, 솔루션의 정확성에 영향을 주지 않는 몇개의 타입을 추측합니다.

// who knows
type Context = { c: string };
declare function doSomething(c: Context, payload: string): number;
declare function doSomethingWithNoPayload(c: Context): boolean;

const actions = {
  first(context: Context, payload: string) { return doSomething(context, payload); },
  second(context: Context) { return doSomethingWithNoPayload(context); }
}

type Actions = typeof actions;

TypeScript 3.0에서는 함수 파라미터 목록을 나타내기 위해 튜플을 사용하는 지원이 도입되었습니다.이것으로 우리는Parameters<FuncType>type alias: 사용 중인 태플을 반환하는 type alias.하지만 일반적으로 튜플을 조작할 수 있는 더 많은 기능도 제공합니다.여기서 정의하겠습니다.Tail<T>(태플 타입을 사용합니다.T첫 번째 요소가 삭제된 새로운 태플을 반환합니다.

// strip the first element off a tuple
// e.g., Tail<[1,2,3]> is [2,3]
type Tail<T extends readonly any[]> =
  ((...t: T) => void) extends ((h: any, ...r: infer R) => void) ? R : never;

그 다음에, 1개의 서명을 할 수 있습니다.dispatch()한 가지 유형의 인수가 필요하다.A, 및 타입의 rest 파라미터Tail<Parameters<Actions[A]>>.

// use rest tuples
declare function dispatch<A extends keyof Actions>(
  action: A, ...payload: Tail<Parameters<Actions[A]>>
): ReturnType<Actions[A]>;

이것으로 원하는 동작을 정확하게 할 수 있습니다.

dispatch("first") // error, no payload specified
dispatch("first", false) // error, payload type is not correct
dispatch("first", "correct") // ok, payload type is correct

dispatch("second", "something") // error, shouldn't pass payload`
dispatch("second") // ok, payload is not passed
dispatch("third") // error, non-existent action

좋은 것 같군요.그게 도움이 되길 바래. 행운을 빌어!

코드로의 링크

언급URL : https://stackoverflow.com/questions/56824647/optionally-required-parameters-in-typescript

반응형