👶 TypeScript

제네릭 타입 추론

개발자 린다씨 2023. 1. 13. 12:00
반응형

제네릭 타입 추론

대부분의 상황에서 TypeScript는 제네릭 타입을 잘 추론해 냅니다. 

function map<T,U>(array: T[], f: (item: T) => U): U[] {
    let result = []
    for (let i = 0; i < array.length; i++){
        result[i] = f(array[i])
    }
    return result
}

map(
    ['a', 'b', 'c'], // T 타입의 배열
    _=> _ === 'a' // U 타입을 반환하는 함수
)

위의 코드 map 함수를 함수 아래처럼 호출하면 TypeScript는 T를 string으로, U를 boolean으로 추론합니다.

 

그러나 제네릭도 명시적으로 지정할 수 있습니다. 제네릭 타입을 명시할 땐 모든 필요한 제네릭 타입을 명시하거나 반대로 아무것도 명시해선 안 됩니다.

map<string, boolean>(
    ['a', 'b', 'c'], 
    _=> _ === 'a' 
)

map<string>( // 2개의 형식 인수가 필요한데 1개를 가져왔습니다.ts(2558)
    ['a', 'b', 'c'], 
    _=> _ === 'a' 
)

TypeScript는 추론된 각 제네릭 타입을 명시적으로 한정한 제네릭에 할당할 수 있는지 확인합니다. 할당할 수 없으면 에러가 발생합니다.

// boolean은 boolean | string에 할당할 수 있으므로 에러 안남
map<string, boolean | string>(
    ['a', 'b', 'c'], 
    _=> _ === 'a' 
)

map<string, number>(
    ['a', 'b', 'c'], 
    _=> _ === 'a' // 'boolean' 형식은 'number' 형식에 할당할 수 없습니다.ts(2322)
)

TypeScript는 제네릭 함수로 전달한 인수의 정보를 이용해 제네릭의 구체 타입을 추론하므로 때로는 아래와 같은 상황이 벌어질 수 있습니다.

let promise = new Promise(resolve =>
        resolve(45)
)

promise.then(result => // {}로 추론함. error TS2362: 수학 연산의 왼쪽 연산자는 'any', 'number', 'bigint', 'enum' 타입 중 하나여야 함
        result*4
)

TypeScript가 result를 {}로 추론한 이유는 TypeScript에 충분한 정보를 제공하지 않았기 때문입니다.

 

TypeScript는 제네릭 함수의 인수에만 의지하여 제네릭 타입을 추론하는데, 인수가 아무것도 없으니 기본적으로 T를 {}로 간주한 것입니다.

 

Promise의 제네릭 타입 매개변수를 명시해서 위의 문제를 해결할 수 있습니다.

let promise = new Promise<number>(resolve =>
    resolve(45)
)

promise.then(result => 
    result * 4
)
반응형