Gwangju-Web-Study / WoowahanTS_Study

✏️우아한 타입스크립트 with 리액트 스터디
6 stars 2 forks source link

3.2.6 특정 문자가 들어간 타입 #13

Closed hyeonseong2023 closed 2 weeks ago

hyeonseong2023 commented 3 weeks ago

📝 105p ❓ 특정 문자가 들어간 타입을 만들어보세요! 책에서 템플릿 리터럴의 예시로 특정 유니온 멤버 뒤에 문자열을 덧붙인 새로운 유니온 타입을 소개했습니다. 이와 비슷하게, 특정 문자열을 가진 값만을 허용하는 새로운 타입을 만들어주세요!

규칙

  1. 제네릭템플릿 리터럴 타입을 사용해서 자유롭게 구현해주세요.
  2. 'ing' 접미사를 가진 단어만 허용하는 타입을 만들어주세요.
  3. 새로 생성할 타입의 이름은 'EndAndIng로 해주세요.
fe-Jay commented 2 weeks ago
// 1. 제네릭 타입 T를 선언하며 이 타입은 문자열만 허용 || never
type EndAndIng<T extends string> = T extends `${string}ing` ? T : never;

// 2. 유니온 타입 선별 결과: "running" | "swimming"
type ValidWords = EndAndIng<"running" | "swimming" | "kendo" | "walk">;

// 3. 테스트
const validWord: ValidWords = "swimming"; // OK
const invalidWord: ValidWords = "kendo"; // 오류: Type '"kendo"' is not assignable to type 'ValidWords'.

// 4. 함수에서의 사용 예시
function processIngWord<T extends string>(word: EndAndIng<T>) {
  console.log(`Processing: ${word}`);
}

processIngWord("jumping"); // OK
processIngWord("walk"); // 오류: Argument of type '"walk"' is not assignable to parameter of type 'EndAndIng<"walk">'
gwangminjun commented 2 weeks ago
// 선언
type EndAndIng<T extends string> = T extends `${string}ing` ? T : never;

// 올바른 사용
type Searching = EndAndIng<'Searching'>; // 'Searching'
type Studying = EndAndIng<'Studying'>; // 'Studying'

// 오류
type Search = EndAndIng<'Search'>; // never
type Study = EndAndIng<'Study'>;   // never

// 제네릭 함수와 함께 사용 예시
function useIngWord<T extends string>(word: EndAndIng<T>): T {

    if (word === (undefined as never)) {
        throw new Error("The word must end with 'ing'.");
    }
    return word;
}

try {
    const validWord = useIngWord('Swimming'); // 정상 작동
    console.log(validWord); // 출력: Swimming
} catch (error) {
    console.error((error as Error).message);
}

try {
    const invalidWord = useIngWord('Swim'); // 컴파일 타임 에러 발생
    console.log(invalidWord);
} catch (error) {
    console.error((error as Error).message); // 추후에 swim 이 아닌 입력값으로 검증해야 할때 런타임 에러 발생을 위해 추가
}
hyeonseong2023 commented 2 weeks ago

모범답안

type EndAndIng<T extends `${string}ing`> = T;

🚫그러나 몇 가지 문제가 있는데...

  1. 유니온 타입

    // 에러가 발생하지 않는다
    EndAndIng<"swimming" | "walk">;  // never
  2. 타입 확장

    const act = "swimming" as string;
    type Active = EndAndIng<typeof action>;
    //혹은
    type Active = EndAndIng<string>;

😎 타입 패턴을 추론하는 infer 키워드를 사용하면 위와 같은 상황에서 더욱 구체적인 타입 지정이 가능하다.

BaekWeb commented 2 weeks ago
// 선언
type EndAndIng<T extends string> = T extends `${string}ing` ? T : never;

// 올바른 사용
type running = EndAndIng<'running'>;  //  'running' 타입

// 잘못된 사용
type walk = EndAndIng<'walk'>;     //  never 타입

function checkIfIng(value: string): void {
    if (value.endsWith('ing')) {
        console.log(`The value '${value}' is valid and ends with 'ing'.`);
    } else {
        console.error(`Error: The value '${value}' does not end with 'ing'.`);
    }
}

// 사용 예시
checkIfIng('running');  // 올바른 값
checkIfIng('walk');     // 잘못된 값