TypeScript의 조건부 유형


65

TypeScript에서 조건부 유형을 사용할 수 있는지 궁금합니다.

현재 다음 인터페이스가 있습니다.

interface ValidationResult {
  isValid: boolean;
  errorText?: string;
}

하지만 제거 할 errorText때, 그리고 단지 그것을 가지고 isValid있다 falseA와 필요한 속성입니다.

나는 그것을 다음 인터페이스로 쓸 수 있었으면 좋겠다.

interface ValidationResult {
  isValid: true;
}

interface ValidationResult {
  isValid: false;
  errorText: string;
}

그러나 아시다시피 불가능합니다. 이 상황에 대한 당신의 생각은 무엇입니까?


때 당신은 의미합니까 isValid이다 false?
특정 성능

18
그러면 isValid가 중복됩니다. errorText가있을 수 있으며 errorText가 null이면 오류가 없습니다.
MTilsted

예, @MTilsted, 당신 말이 맞습니다. 그러나 우리는 레거시 코드 때문에이를 유지해야합니다.
Arman

답변:


89

이러한 종류의 논리를 모델링하는 한 가지 방법은 다음과 같은 공용체 유형을 사용하는 것입니다.

interface Valid {
  isValid: true
}

interface Invalid {
  isValid: false
  errorText: string
}

type ValidationResult = Valid | Invalid

const validate = (n: number): ValidationResult => {
  return n === 4 ? { isValid: true } : { isValid: false, errorText: "num is not 4" }
}

그런 다음 컴파일러는 부울 플래그에 따라 유형을 좁힐 수 있습니다.

const getErrorTextIfPresent = (r: ValidationResult): string | null => {
  return r.isValid ? null : r.errorText
}

7
좋은 대답입니다. 그리고 컴파일러는 실제로 여기 r에 유형이어야한다고 말할 수 Invalid있습니다.
sleske

1
이것을 차별 노동 조합이라고합니다. 아주 멋진 물건 : typescriptlang.org/docs/handbook/...
Umur Kontacı

41

세 번째 인터페이스를 만드는 데만 사용되는 여러 인터페이스를 만들지 않으려면 type대신 대신 직접 대체 할 수 있습니다 .

type ValidationResult = {
    isValid: false;
    errorText: string;
} | {
    isValid: true;
};

20

버그에 의해 입증 노조 나는이 처리 권장하는 방법입니다. 그럼에도 불구하고 Typescript 에는conditional types ”라는 것이 있으며이를 처리 할 수 ​​있습니다.

type ValidationResult<IsValid extends boolean = boolean> = (IsValid extends true
    ? { isValid: IsValid; }
    : { isValid: IsValid; errorText: string; }
);


declare const validation: ValidationResult;
if (!validation.isValid) {
    validation.errorText;
}

이것은 ValidationResult(실제로 ValidationResult<boolean>기본 매개 변수로 인해) 버그 응답 또는 CertainPerformance의 응답 에서 생성 된 공용체 와 동일하며 동일한 방식으로 사용할 수 있습니다.

여기 장점은 또한 알려져 주위를 전달할 수 있다는 것입니다 ValidationResult<false>값을 한 다음 테스트를하지 않았을 isValid이를 것으로 알려진 것 같이 false하고 errorString존재하는 것으로 알려진 될 것이다. 아마도 이런 경우에는 필요하지 않으며 조건부 유형은 복잡하고 디버깅하기 어려울 수 있으므로 불필요하게 사용해서는 안됩니다. 그러나 당신은 할 수 있었고 언급 할 가치가있는 것처럼 보였습니다.


3
나는 이것이 실제로 도움이 될 것이라고 확신합니다. 그러나 나에게 구문은 정말 불쾌 해 보입니다.
Peilonrayz

3
@Peilonrayz Eh, 다른 Typescript 코딩과 일관성이 좋으며 extends사용하기에 적합한 연산자입니다. 또한 매우 강력합니다. 특히 유형을 파헤 치기 위해 사용할 수도 있기 때문 type SecondOf<T> = T extends Pair<any, infer U> ? U : never;입니다.
KRyan December

@ KRyan 나는 그것에 대해 생각하고있다. 기본적으로 SecondOf<number>'확장'을 의미합니까 Pair<any, number>? "표지로 책을 판단하지 마십시오"라는 문구가 여기에 해당한다고 생각합니다.
Peilonrayz

@Peilonrayz 아, 아니; 오히려 반대입니다. SecondOf<Pair<any, number>>로 평가됩니다 number. SecondOf<number>평가하여이하기 never때문에, number extends Pair<any, infer U>거짓, 같은 number어떤 확장하지 않습니다Pair
KRyan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.