IT이야기

vuex 저장소를 입력하는 일반 유형

cyworld 2022. 6. 9. 22:11
반응형

vuex 저장소를 입력하는 일반 유형

입력 힌트를 증명하는 범용 타입을 작성하려고 합니다.Vuex돌연변이기사 Vuex + TypeScript를 읽고 좀 더 일반적인 것을 만들겠다는 영감을 얻었습니다.이런 생각이 들었어요.

export type MutationType<S, P, K extends keyof P> = Record<K, (state: S, payload: P[K]) => void>;

// S
export type DiceGameState = {
  round: number;
  score: number;
  diceItems: DiceHistoryItem[];
};

// P
export interface DiceGameMutationPayloadMap {
  INCREMENT_SCORE: number;
  DECREMENT_ROUND: number;
  ADD_DICE_HISTORY_ITEM: DiceHistoryItem;
}

// K
export enum DiceGameMutationsKeys {
  INCREMENT_SCORE = 'INCREMENT_SCORE',
  DECREMENT_ROUND = 'DECREMENT_ROUND',
  ADD_DICE_HISTORY_ITEM = 'ADD_DICE_HISTORY_ITEM'
}

export type DiceStoreMutation = MutationType<
  DiceGameState,
  DiceGameMutationPayloadMap,
  keyof typeof DiceGameMutationsKeys
>;

export const mutations: MutationTree<DiceGameState> & DiceStoreMutation = {
  DECREMENT_ROUND: (state: DiceGameState, payload: number) => {},
  INCREMENT_SCORE: (state: DiceGameState, payload: number) => {},
  ADD_DICE_HISTORY_ITEM: (state: DiceGameState, payload: DiceHistoryItem) => {}
};

장소:

  • S → 돌연변이 상태 유형
  • P → 돌연변이 이름과 이 돌연변이에 할당된 페이로드 유형의 지도
  • K → 돌연변이명

만약 내가 이것의 세부사항을 알 수 있습니다.MutationTypeIDE에서는 다음과 같은 힌트를 얻을 수 있습니다.

여기에 이미지 설명 입력

이 오브젝트의 키는 다음 중 하나입니다.Kkeys 및 value는 state를 취하는 메서드이며, 그 타입은S및 payload는 할당된 값의 유형입니다.P.

이 코드를 컴파일하려고 하면 다음 오류가 나타납니다.

오류: (7, 3) TS2322: ' (상태:DiceGameState, payload: number) => void'는 유형 '(상태:DiceGameState, 페이로드: number | DiceHistoryItem) => void' 입니다.'payload'와 'payload' 매개 변수의 유형이 호환되지 않습니다.'number | DiceHistory'를 입력합니다.항목'은 '번호' 유형에 할당할 수 없습니다.'DiceHistory' 입력항목'은 '번호' 유형에 할당할 수 없습니다.

내 제네릭을 어떻게 작동시킬 수 있는지 아세요?

예제:

특정 변환명의 payload 타입을 TS에 유추하고 싶다.예를 들어 다음과 같은 이름의 변이가 있는 경우INCREMENT_SCORE그럼 타입은payload TS에 의해 암시된 숫자는 숫자여야 합니다.이것이 제가 이것을 만든 이유입니다.DiceGameMutationPayloadMap작성 후,const mutations. typescript는 (변환명을 기반으로) 어떤 유형의 payload를 가져야 하는지 알려줘야 합니다.

그 좋은 예로는,addEventListenrTypeScript에서 제공하는 메서드입니다.이 유형은 이벤트 유형을 유추합니다(ev)는 지정된 이벤트명을 기반으로 합니다.type):

addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLButtonElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;

이 유형에 대한 자세한 내용은 lib.dom.ts line 6385를 확인하십시오.

사실, 가능합니다.내가 무엇을 잘못하고 있는지 깨닫는 데 시간이 좀 걸리지만 결국 나는 나의 실수를 이해했다.

나의 첫 번째 실수는 안에 있었다.DiceStoreMutation왜냐하면 이 범용의 세 번째 인수는 key no key name의 유형을 언급하고 있기 때문입니다.이 증거는 첨부된 스크린샷에서 확인할 수 있습니다.

여기에 이미지 설명 입력

[ Expanded ]는 실제로는 문자열이지만 스트링 리터럴의 조합임을 알 수 있습니다.어쩌면 내가 그냥 이 모든 걸 이용해서keyof DiceGameMutationsKeyskeyof typeof DiceGameMutationsKeys키 타입이 아닌 이 인터페이스의 키명을 참조합니다만, 물론 이것은 예상대로 에러가 발생했습니다.그래서 어떻게든 제네릭을 바꿔야겠다는 생각이 들었다.내가 @Joel Bourbonnais의 답변을 읽은 후, 그리고 이 매우 좋은 예시를 체크한 후에P[K] being being being being being being being 의 부분Index types새로운 아이디어가 떠올랐습니다.Mapped generics+Index types은 다음과 같은 이 새로운 타입은 다음과 같은 형태를 생각해냈습니다.

export type MutationType<T, U> = {
  [K in keyof U]: (state: T, payload: U[K]) => void;
};

딱 한 가지만 말할 수 있어요 그게 효과가 있어요이젠 필요조차 없어DiceGameMutationsKeysDiceGameMutationPayloadMap에 모든 정보를 나타냅니다.왜런런 어어 ?어 ???을 사용하다

  • 은은 firstlyK in keyof UK밖에 없다U그래서 그것은 스팅 리터럴의 결합이 될 것이다.U키 인터페이스
  • 번째, ㅇㅇㅇㅇㅇ,U[K]그래서 그것은 일종의 검색일 것이다.UK 중 하나)U interface를 합니다.

아래에서 증명된 스크린샷을 찾을 수 있습니다.

여기에 이미지 설명 입력

언급URL : https://stackoverflow.com/questions/64836903/generic-type-for-typing-vuex-store

반응형