타입스크립트가 코드를 해석해 나가는 동작을 의미
할당값
을 기준으로 추론
let x = 3; //number로 추론
let isValid = true; //boolean으로 추론
let names = “수빈”; //string으로 추론
return문
을 기준으로 추론
반환값이 따로 없으면 void
로 추론
function printHello() { //string으로 추론
return "Hello!";
}
function isTrue() { //boolean으로 추론
if(1+2 == 3) return true;
else return false;
}
파라미터의 기본값
을 기준으로 타입을 추론
function addNum(x=10, y=3) { //x,y,addNum은 모두 number로 추론된다.
return x+y;
}
function isOdd(x=10, y=3) { //x,y는 number로 isOdd는 boolean으로 추론
if(x+y % 2 == 0) return false;
else return true;
}
(상속에 관한 인터페이스 타입 추론)
class 부모클래스 {
String 부모필드;
}
class 자식클래스 extends 부모클래스 {
String 자식필드;
}
부모클래스 변수 = new 자식클래스(); // 부모클래스 타입 변수이지만, 자식클래스는 부모클래스를 상속(포함)하기에, 생성까지는 문제 없음
변수.부모필드; // 사용하는데 문제없음
변수.자식필드; // ERROR - 하지만 할당된 변수는 부모클래스 타입이기 때문에 자식클래스에만 있는 필드를 접근할 경우 에러가 뜨게 된다.
부모 클래스를 상속한 자식 클래스를 new 생성자로 생성할때
변수의 타입을 부모 클래스로 지정해 생성할 수 있다는 원리에서 따온 개념!
interface TSgirls {
name: string;
age: number;
}
interface YB extends TSgirls {
doSopkathon: boolean;
}
interface OB extends TSgirls {
didAppjam: boolean;
}
const p1: TSgirls = { name: 'hyein', age: 24 };
const p2: YB = { name: "subin", age: 22, doSopkathon: true };
const p3: OB = { name: "hyein", age: 24, didAppjam: true };
const arr1 = [p1, p2, p3]; // const arr1: TSgirls[]
const arr2 = [p2, p3]; // const arr2: (YB | OB)[]
👀 arr1 과 arr2 의 타입은 어떻게 추론 될까?
바로 다른 타입으로 할당 가능한 타입은 제거가 되는데, YB와 OB 인터페이스는 둘다 TSgirls에 할당이 가능하기 때문에 ➡️ arr1
변수의 타입은 둘다 제거가 되고 TSgirls
타입만 남게 된다
arr2
는 YB
와 OB
타입의 변수를 받는데, 이 둘은 서로 상속되는 관계가 아니기 때문에 별개의 타입으로 취급된다. ➡️ 따라서 두개의 타입을 묶는 유니온 타입
으로 추론이 된다
함수를 호출할 때 전달되는 값으로부터 타입을 추론
function sayHello<T>(arg: T): T {
return arg;
}
// 제네릭 타입을 명시적으로 지정하지 않아도, 타입스크립트가 추론하여 타입을 결정
let result = sayHello("Hello, TypeScript!");
개발자가 해당 타입에 대해 확신이 있을 때 사용하는 타입 지정 방식
const name: string = 'subin';
1️⃣ as
키워드를 이용
const name = 'subin' as string;
2️⃣ <타입>
을 변수에 부여
const name = <string>'subin'
이 둘 중에서는 as
키워드를 더 많이 사용한다 ( 두 번째 경우는 HTML 태그 등과 혼동될 수 있기 때문! )
타입 단언은 타입 선언 혹은 타입을 변환하는 Type Casting과는 달리, 실제 데이터 타입을 변경하지 않고 에러만 방지하는 기능을 합니다!
타입 단언은 타입 에러를 없애줄 뿐 런타임 에러를 막아주지 않는다
💡 즉, 컴파일 타입에 잡을 수 있는 에러를 없앰으로서 원래대로면 생기지 않았을 런타임 에러를 발생시킬 수 있다.
interface human {
sayhi: string;
age: number;
}
let person = {
// 아무것도 안 넣음
} as human;
console.log(person.sayhi)
👀 무슨 일이 일어날까!!
당연히 에러가 발생!! ➡️ 하지만 런타임에 에러가 날 것이다.
타입 단언
을 사용했기 때문에 오류가 난 코드를 컴파일 단계
에서 발견하지 못하고 런타임 단계
까지 가서야 발견하게하였다. ▶️ 이는 타입스크립트를 사용하는 큰 장점을 무시한 셈!!!!
값을 any
타입으로 단언하게 되면 특정 값에 대한 타입 검사를 사실상 완전히 무효화할 수 있다.
(3 as any).substr(0, 3);
위 코드는 실제로 실행한다면 런타임 에러
가 발생하지만, 타입 검사
는 통과한다.
번거로운 타입 검사를 피할 수 있지만, any를 사용한 타입 단언은 어쩔 수 없는 경우를 제외하곤 피하는 것이 좋다. ➡️ any를 사용한 타입 단언은 타입스크립트를 사용하는 근본적인 이유에 정확히 반하기 때문이다.
우리는 calculateButton
이 적확히 HTMLButtonElement
일 수 밖에 없다는 것을 알고있다
이럴 때 타입 단언
을 사용한다
!
를 이용하여 그 값이 null이 아니라는 단언한다.JSON.parse
를 거치고 난 값은 any
타입이다
파싱한 후에 타입을 갖게하기 위해서 타입 단언
을 사용한다