TypeScript 문자열 리터럴 유형 연결
15514 단어 tutorialtypescriptprogramming
const a = "foo"; // Inferred type: const a: "foo"
그러나 상수를 결합할 때 문자열의 내용이 컴파일 시간에 알려지더라도 유형이 일반
string
으로 좁혀집니다.const a = "foo"; // const a: "foo"
const b = "bar"; // const b: "bar"
const combined = `${a}${b}`; // Inferred type: const combined: string
// What you'd expect: const combined: "foobar"
해결책
조인된 문자열에 리터럴 유형을 유지하기 위해 사용자 지정 조인 함수를 사용했습니다.
function join<T extends string[]>(...strings: T): Concat<T> {
return strings.join("") as Concat<T>;
}
이를 통해 일반 유형 T는 조인 함수에 전달되는 문자열 리터럴의 배열입니다. 이제 필요한 것은 다음과 같이 문자열 리터럴의 배열을 가져와 단일 문자열 리터럴로 바꾸는
Concat
유틸리티 유형을 구현하는 것입니다.type R = Concat<["foo", "bar", "baz"]>; // type R = "foobarbaz"
이 유형의 순진한 구현은 가능한 모든 배열 길이에 대한 유형 연결을 단순히 하드 코딩하는 것일 수 있습니다.
type Concat<T extends string[]> = T["length"] extends 1
? T[0]
: T["length"] extends 2
? `${T[0]}${T[1]}`
: T["length"] extends 3
? `${T[0]}${T[1]}${T[2]}`
: T["length"] extends 4
? `${T[0]}${T[1]}${T[2]}${T[3]}`
: T["length"] extends 5
? `${T[0]}${T[1]}${T[2]}${T[3]}${T[4]}`
: never;
그러나 이 방법으로 연결할 수 있는 문자열 리터럴 수에 제한이 있으므로 매우 제한적입니다.
유형 재귀를 통한 연결
임의의 수의 문자열 리터럴을 허용하기 위해 추론, 배열 유형 구조 분해 및 재귀를 사용할 수 있습니다.
export type Concat<T extends string[]> = T extends [
infer F,
...infer R
]
? F extends string
? R extends string[]
? `${F}${Concat<R>}`
: never
: never
: '';
어떻게 작동합니까?
먼저
T extends [infer F, ...infer R]
, T 배열의 첫 번째 요소를 검색하여 F에 할당하고 나머지 요소를 가져와서 R에 할당합니다. 예를 들어 T 유형이 ["foo", "bar", "baz"]
인 경우 F는 type F = "foo"
가 됩니다. R은 type R = ["bar", "baz"]
가 됩니다.그런 다음
F extends string
및 R extends string[]
는 F와 R이 우리가 기대하는 유형인지 확인하고 이러한 조건은 항상 충족되어야 하며 작성할 필요가 없어야 하지만 TypeScript 엔진은 이 조건이 없으면 오류를 발생시킵니다.마지막으로 문자열 리터럴 유형이 반환되며 문자열 리터럴의 시작 부분에 F가 있고 결과는
Concat<R>
입니다.이전의 일반
join
함수와 쌍을 이룬 이 유형 유틸리티는 문자열 상수를 결합하고 문자열 리터럴 유형을 유지할 수 있는 훌륭한 도구를 제공합니다.보너스
TypeScript 버전 4.7 이상에서는 Concat 유틸리티 유형을 다음과 같이 단순화할 수 있습니다.
export type Concat<T extends string[]> = T extends [
infer F extends string,
...infer R extends string[]
] ? `${F}${Concat<R>}` : '';
다음은 구분 기호가 있는 조인 함수 및 Concat 유틸리티 유형입니다.
export type PrependIfDefined<T extends string, S extends string> = T extends "" ? T : `${S}${T}`;
export type ConcatS<T extends string[], S extends string> = T extends [
infer F extends string,
...infer R extends string[]
] ? `${F}${PrependIfDefined<ConcatS<R, S>, S>}` : '';
function joinWithSeparator<S extends string>(separator: S) {
return function <T extends string[]>(...strings: T): ConcatS<T, S> {
return strings.join(separator) as ConcatS<T, S>;
}
}
// Usage
const result = joinWithSeparator(":")("foo", "bar", "baz"); // const result: "foo:bar:baz"
playground!에서 이 코드를 확인하십시오.
Reference
이 문제에 관하여(TypeScript 문자열 리터럴 유형 연결), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ncpa0cpl/typescript-concatenate-multiple-string-literals-c59텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)