모든변수에 타입을 선언 하는 것은 매우 비생산적입니다.
타입 추론이 가능하다면 명시적인 타입 선언은 필요하지 않기 때문입니다.
let x:number = 12;
let x = 12; //타입추론이 가능하므로 굳이 타입선언을 해줄 필요 없음
더 복잡한 객체/배열 인 경우도 타입 추론이 가능합니다.
const person = {
name: "Truth",
born: {
where: "Seoul",
when: "c.1919",
},
died:{
where: "Seoul",
when: "c.1919",
}
}//객체
function square(nums: number[]){
return nums.map(x =>x *x);
}
const squares = square([1,2,3]) // number[];
비구조화 할당문은 모든 지역 변수의 타입이 추론되도록 합니다.
여기에 추가적으로 명시적 타입 구문을 넣을 시 불필요한 타입 선언으로 코드가 번잡해 질 수 있음!
function logProduct(product:Product){
const {id,name,price}= prodict //비구조화 할당
}
타입스크립트는 최종 사용처까지 고려하지 않고 타입스크립트에서 변수와 타입은 일반적으로 처음 등장할 때 결정됩니다.
단! 라이브러리를 사용할 때 타입 정보가 기본적으로 제공된다면 콜백함수 매개변수 타입은 자동으로 추론딥니다.
타입구문을 제거하면 잉여 속성 체크가 동작하지 않아서 선언한 곳이 아닌 사용되는 곳에서 타입 오류가 발생합니다.
=>타입구문을 쓴다면 실수가 발생한 그부분에 오류를 표시해줍니다.
++linter를 사용한다면 no-inferrable-types를 사용해서 모든 타입구문이 정말 필요한지 확인 할 수 있습니다
중복되는 변수를 사용할 경우 타입 정의 시 혼란이 올 수 있습니다.
타입스크립트에서의 과정으로 지정된 단일 값을 가지고 할당 가능한 값들의 집합을 유추해야 한다는 뜻입니다
let대신 const로 변수를 선언시 재할당이 불가능 하기 때문에 타입스크립트는 좁은 타입으로 추론이 가능하다.
객체의 경우 타입스크립트의 넓히기 알고리즘은 각 요소를 let으로 할당된 것처럼 다룬다.
const x ='x'//타입이 "x" let vec ={x:10,y:20,z:30}
const v: { x: 1 | 3 | 5 } = {
x: 1,
};
const v1 = {
x: 1,
y: 2,
}; // type : {x: number; y: number;}
const v2 = {
x: 1 as const,
y: 2,
}; // type : {x: 1; y: number;}
const v3 = {
x: 1,
y: 2,
} as const; // type : {readonly x: 1; readonly y: 2;}
타입스크립트가 넓은 타입으로부터 좁은 타입으로 진행하는 과정. ex) null 체크
const el = document.getElementById("foo"); // type : HTMLElement | null
if (el) {
// type : HTMLElement
el.innerHTML = "1";
} else {
// type : null
alert("no element");
}
if (!el) throw new Error("no element"); // type : null
el.innerHTML = "1"; // type : HTMLElement
이외에도 instanceof,속성 체크,Array.isArray 같은 내장 함수등으로 타입을 좁힐 수 있다.
또다른 방법으로는 명시적'태그'를 붙이는 방법이다.
=>사용자 정의 타입 가드 이용하는 방법이 있다.
function isInputElement(el: HTMLElement): el is HTMLInputElement {
return "value" in el;
}
function getElementContent(el: HTMLElement) {
if (isInputElement(el)) {
el; // type : HTMLInputElement
return el.value;
}
el; // type : HTMLElement
return el.textContent;
}
interface Point {
x: number;
y: number;
}
const pt: Point = {}; // x ~'{}' 형식에 'Point' 형식의 x, y 속성이 없습니다.
const pt: Point = {
x: 3,
y: 4,
}; // 정상
// 객체를 반드시 제각각 나눠서 만들어야 할땐 단언문을 사용하자
const pt = {} as Point;
pt.x = 3;
pt.y = 4;
const pt = { x: 3, y: 4 };
const id = { name: "Pythagoras" };
const namedPoint = {};
Object.assign(namedPoint, pt, id);
namedPoint.name; // x ~~~ '{}' 형식에 'name'속성이 없습니다.
// 객체 전개 연산자 (...) 사용
const namedPoint = { ...pt, ...id };
namedPoint.name; // 정상
declar let hasMiddle: boolean;
const firstLast = {first: 'Harry', last: 'Truman'};
const president = {...firstlast, ...(hasMiddle ? { middle: 'S' } : {})};
const president:{
middle?: string;
first: string;
last: string;
}
속성을 제각각 추가하지 말고 한꺼번에 객체로 만들어야합니다.
안전한 타입으로 속성을 추가하려면 객체 전개({...a,...b})를 사용하면 됩니다.
객체에 조건부로 속성을 추가하는 방법을 익히도록 합시다.
타입스크립트에서 식별자를 일관성 없이 사용하는 것은 지양해야 한다.
그 이유는 타입 좁히기와 관련이 있다.
interface Coordinate {
x: number;
y: number;
}
interface BoundingBox {
x: [number, number];
y: [number, number];
}
interface Polygon {
exterior: Coordinate[];
holes: Coordinate[][];
bbox?: BoundingBox;
}
function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
const box = polygon.bbox;
if (polygon.bbox) {
if (pt.x < box.x[0]) {
// 객체가 'undefined'일 수 있습니다.
}
}
}
코드는 작동하지만 편집기에서 오류로 표시됩니다
why?
그 이유는 polygon.bbox를 별도의 box라는 별칭을 만들었고,
이 부분이 제어 흐름 분석을 방해했기 때문입니다.
polygon.bbox의 타입은 정제했지만 box는 그렇지 않기 때문에 오류가 발생한 것!
콜백보다는 프로미스나 async/await를 사용해야하는 이유?
프로미스를 사용하면 타입스크립트의 모든 타입 추론이 제대로 동작한다
✔ 프로미스를 생성하기보다는 async/await를 사용해야 하는 이유?
변수를 let / const 키워드를 이용하여 선언할 때 타입 추론
//let의경우
let language = "JavaScript";
type LaunguageType = typeof language;
// 타입은 string
//const의 경우
const language = "JavaScript";
type LaunguageType = typeof language;
// 타입은 "JavaScript"
let language: Language = "Javascript";
setLanguage(language); // 정상
const language = "Javascript";
setLanguage(language); // 정상
function panTo(where: [number, number]) {
/* ... */
}
panTo([1, 2]); // 정상
const loc = [1, 2];
panTo(loc); // 'number[]' 형식의 인수는 '[number, number]' 형식의 매개변수에 할당될 수 없습니다.
const 키워드를 통해 선언한 변수는 얕은(shallow) 상수라고 한다.
선언을 할 때 변수를 깊은(deeply) 상수로 선언을 하려면 as const 를 사용한다.
값이 내부까지 상수라는 사실을 타입스크립트에게 알려준다.
단 위처럼 할 시 readonly로 인해 너무 과하게 정확해집니다
타입 흐름을 개선하고, 가독성을 높이고, 명시적인 타입 구문의 필요성을 줄이기 위해 직접 구현하기보다는 내장된 함수형 기법과 lodash 같은 유틸리티 라이브러리를 사용하는 것이 좋다