const furby: Product = {
name: 'Furby',
id: 630509430963,
// ~~ Type 'number' is not assignable to type 'string'
price: 35,
};
logProduct(furby);
// 직접적으로 오류 잡아줌
const cache: {[ticker: string]: number} = {};
function getQuote(ticker: string): Promise<number> {
if (ticker in cache) {
return cache[ticker];
// ~~~ Type 'number' is not assignable to type 'Promise<number>'
}
// ...
}
타입 좁히는 방법 : 일반적으로 코드문맥에서 조건문으로 타입가드를 한다.
그렇지만 조건문으로 narrowing을 할 수 없는 상황이라면? 다른 방법을 고려해본다.
태그기법 => type이라는 태그를 통해 좁혀준다.
interface UploadEvent { type: 'upload'; filename: string; contents: string }
interface DownloadEvent { type: 'download'; filename: string; }
type AppEvent = UploadEvent | DownloadEvent;
function handleEvent(e: AppEvent) {
switch (e.type) {
case 'download':
console.log('Download', e.filename);
// ^? (parameter) e: DownloadEvent
break;
case 'upload':
console.log('Upload', e.filename, e.contents.length, 'bytes');
// ^? (parameter) e: UploadEvent
break;
}
}
타입 단언 함수 도입(사용자 정의 타입 가드)
반환값이 true인경우 => type을 HTMLInputElement로 좁힌다.
function isInputElement(el: Element): el is HTMLInputElement {
return 'value' in el;
}
function getElementContent(el: HTMLElement) {
if (isInputElement(el)) {
return el.value;
// ^? (parameter) el: HTMLInputElement
}
return el.textContent;
// ^? (parameter) el: HTMLElement
}
// Parameter is a (latitude, longitude) pair.
function panTo(where: [number, number]) { /* ... */ }
panTo([10, 20]); // OK
const loc = [10, 20];
// ^? const loc: number[]
panTo(loc);
// ~~~ Argument of type 'number[]' is not assignable to
// parameter of type '[number, number]
const loc = [10, 20] as const;
// ^? const loc: readonly [10, 20]
panTo(loc);
// ~~~ The type 'readonly [10, 20]' is 'readonly'
// and cannot be assigned to the mutable type '[number, number]'
두가지 case모두 문제발생 => 첫번째는 number[]형으로 너무 넓어서, 두번째는 너무 좁아서 발생한다. readonly가 아니라서.
가장 좋은 해결책은 => panTo의 파라미터에 readonly를 추가하는 것. 근데 안된다면?
function panTo(where: readonly [number, number]) { /* ... */ }
const loc = [10, 20] as const;
panTo(loc); // OK
const loc = [10, 20, 30] as const; // error is really here.
panTo(loc);
// ~~~ Argument of type 'readonly [10, 20, 30]' is not assignable to
// parameter of type 'readonly [number, number]'
// Source has 3 element(s) but target allows only 2.
interface Layer {
layout: FillLayout | LineLayout | PointLayout;
paint: FillPaint | LinePaint | PointPaint;
}
// xxxxxx
interface FillLayer {
layout: FillLayout;
paint: FillPaint;
}
interface LineLayer {
layout: LineLayout;
paint: LinePaint;
}
interface PointLayer {
layout: PointLayout;
paint: PointPaint;
}
type Layer = FillLayer | LineLayer | PointLayer;
// oo