>웹 프론트엔드 >JS 튜토리얼 >재귀 조건부 유형

재귀 조건부 유형

Barbara Streisand
Barbara Streisand원래의
2024-12-01 03:00:13462검색

Recursive Conditional Types

for in 루프가 있는데 갑자기 변수 유형이 문자열 리터럴 공용체 유형이 아니라 문자열이라는 것을 깨달았다고 가정해 보겠습니다. 따라서 tsc를 사용하여 앱을 컴파일할 때 다음과 같은 추악한 오류가 발생하며, 여러분이 가장 좋아하는 IDE가 다음과 같이 비명을 지르는 경우가 많습니다.

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'.
  No index signature with a parameter of type 'string' was found on type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'.ts(7053)

[!참고]

어떻게 이루어지는지 보여드리기 위해 os.cpus를 사용하고 있습니다. 거기에서 객체인 cpu.times를 반복하려고 합니다. 자세한 내용은 여기에서 확인하실 수 있습니다.

문제가 있는 코드는 다음과 같습니다.

import { cpus } from 'os';

const logicalCoresInfo = cpus();

for (const logicalCoreInfo of logicalCoresInfo) {
  let total = 0;
  for (const type in logicalCoreInfo.times) {
    total += logicalCoreInfo.times[type];  // Darn it, TS is upset!
  }
}

고치다

  1. logicalCoreInfo.times 내부에서 키를 추출하고 거기에서 새로운 유형을 생성해야 합니다.
  2. 그런 다음 유형 어설션을 활용하여 TS에게 모든 것이 훌륭하고 여기서 무슨 일이 일어나고 있는지 알고 있음을 확신시킬 수 있습니다.

자, 먼저 시작해 보겠습니다. 먼저 사용자 정의 유틸리티 유형을 만들어야 합니다. 최종 유틸리티 유형은 다음과 같습니다.

type NestedKeysOf<T, K extends PropertyKey> = T extends object
  ? {
      [TKey in keyof T]-?:
        | (TKey extends K ? keyof T[TKey] : never)
        | NestedKeysOf<T[TKey], K>;
    }[keyof T]
  : never;

분석해 보겠습니다.

  1. T는 객체를 확장합니까? ... : T가 객체인 경우 중첩된 객체 유형 T를 재귀적으로 탐색하고 T 내부의 특정 키의 키를 추출하도록 TS에 지시하지 않습니다.
  2. [TKey in key of T]-? 이 유틸리티 유형에 전달된 객체 내부의 키 이름을 모르기 때문에 여기서 특히 유용한 "매핑 유형"입니다. 여기서는 logicCoreInfo를 해당 객체나 다른 객체에 전달한 다음 키를 반복하여 새로운 유형을 생성합니다.

    그리고 -? 선택성을 제거하여 모든 키의 문자열 리터럴 통합 유형을 갖도록 합니다. 즉, { keyName?: string }은 { keyName: string }으로 처리됩니다.

  3. (TKey는 K ? keyof T[TKey] : never) 반복의 현재 키가 전달된 키(K)와 일치하는지 확인하고, 일치하는 경우 그 안에 있는 모든 키를 문자열 리터럴 결합 유형으로 추출합니다. 그리고 그것을 돌려보내세요. 그렇지 않으면 아무것도 반환하지 않습니다.

  4. 그런 다음 3단계에서 결과가 없으면 이 유틸리티 유형을 T[Tkey]에 재귀적으로 적용합니다. 이렇게 하면 유틸리티 함수가 중첩된 개체에서도 작동합니다. 이를 일반적으로 "재귀 조건부 유형"이라고 합니다.

  5. 마지막으로 매핑된 유형에 의해 생성된 모든 유형의 통합을 가져오도록 요청합니다. 간단히 말해서 우리는 중첩된 구조를 평면화하고 있습니다.

이제 사용할 시간입니다.

interface Person {
  name: string;
  address: {
    street: string;
    city: string;
  };
}

type KeysOfAddress = NestedKeysOf<Person, 'address'>; // "street" | "city"

// Or in our original example:
type CpuTimesKeys = NestedKeysOf<typeof logicalCoreInfo, 'times'>;
// ...
total += logicalCoreInfo.times[type as CpuTimesKeys];
// ...

참조

  • 중첩된 객체 유형의 TypeScript 키입니다.

위 내용은 재귀 조건부 유형의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.