아이템 1 ~ 5 정리본
아이템 1: 타입스크립트와 자바스크립트의 관계 이해하기
모든 자바스크립트는 타입스크립트지만, 모든 타입스크립트는 자바스크립트가 아니다.
let city = 'new york city';
console.log (city.toUppercase());
// 'toUppercase* 속성이 'string* 형식에 없습니다.
// 'toUpperCase1 을(를) 사용하시겠습니까?
city 변수가 문자열이라는 것을 알려주지 않아도 타입스크립트는 초깃값으로부터 타입을 추론한다.
타입 추론은 ts에서 중요한 부분 !!
타입 시스템의 목표
- 런타임에 오류를 발생시킬 코드를 미리 찾아내는 것
하지만, 타입 체커가 모든 오류를 찾아내지는 않음
const states = [
{name: 'Alabama'f capital: 'Montgomery'},
{name: 'Alaska', capital: ’Juneau'},
{name: 'Arizona', capital: 'Phoenix'},
];
for (const state of states) {
console.log(state.capitol);
}
// undefined
// undefined
// undefined
for (const state of states) {
console.log(state.capitol);
// ----------- 'capitol' 속성이 ... 형식에 없습니다.
// 'capital'을(를) 사용하시겠습니까?
}
- 타입스크립트는 어느 쪽이 오타인지 판단하지 못한다.
- 오류의 원인은 추측할 수 있겠지만 항상 정확하지는 않다.
⇒ 명시적으로 states를 선언하여 의도를 분명하게 하자.
interface 사용
interface State {
name: string;
capital: string;
}
const states: State[] = [
{name: 'Alabama', capitol: 'Montgomery'}
// ------------
{name: 'Alaskar', capitol: 'Juneau'},
// ------------
{name: 'Arizona', capitol: 'Phoenix'},
// ------------
// 개체 리터럴은 알려진 속성만 지정할 수 있지만
// 'State' 형식에 'capitol'이(가) 없습니다.
// 'capital'을(를) 쓰려고 했습니까?
// ...
];
for (const state of states) {
console.log(state.capital);
}
의도를 분명하게 하여, 오류가 어디서 발생했는지 찾을 수 있음 !
아이템 2: 타입스크립트 설정 이해하기
command line 으로 설정
$ tsc —noImplicitAny program.ts
or
tsconfig.json 파일로 설정
{
"compilerOptions": {
"noImplicitAny": true
}
}
위 설정을 통해 타입을 제어할 수 있다.
strictNullChecks
- null과 undefined가 모든 타입에서 허용되는지 확인하는 설정
// strictNullChecks = true
const x: number = null; // 정상, null은 유효한 값
// strictNullChecks = false
const x: number = null; // 비정상, 'null' 형식은 'number' 형식에 할당할 수 없습니다.
아이템 3: 코드 생성(컴파일)과 타입이 관계없음을 이해하기
타입스크립트 컴파일러 역할 독립적으로 수행
- ts/js를 브라우저에서 동작할 수 있도록 구버전의 js로 트랜스파일 (번역 + 컴파일)
- 타입 오류 체크
따라서, ts가 js로 변환될 때 코드 내의 타입에는 영향을 주지 않는다.
또한, 자바스크립트의 실행 시점에도 타입은 영향을 미치지 않는다.
타입 오류가 있는 코드도 컴파일이 가능함
컴파일은 타입 체크와 독립적으로 동작하기 때문에, 타입 오류가 있는 코드도 컴파일 가능
cf. C나 자바의 경우 타입 체크와 컴파일이 동시에 이루어짐
오류가 있을 때 컴파일하지 않으려면 ..
- tsconfig.json에 noEmitOnError를 설정하거나 빌드 도구에 적용한다.
런타임에는 타입 체크가 불가능하다
instanceof 체크는 런타임에 일어나지만, Rectangle은 타입이기 때문에 런타임 시점에서 아무것도 할 수 없다.
cf ) instanceof + Class명
런타임에 타입을 지정하기 위해서는 ?
- 런타임에 타입 정보를 유지하는 방법
1. 속성이 존재하는지 체크한다.
2. 런타임에 접근 가능한 타입 정보를 명시적으로 저장하는 ‘태그’ 기법이 있다.
아이템 4: 구조적 타이핑에 익숙해지기
- 자바스크립트는 덕 타이핑 (duck typing) 기반으로, 타입스크립트는 이를 모델링하기 위해 구조적 타이핑을 사용함
덕 타이핑
- 타입을 미리 정하는게 아닌 실행이 되었을 때 해당 method를 확인하여 타입을 정함
구조적 타이핑
- y가 최소한 x와 동일한 멤버를 가지고 있다면 x와 y는 호환된다.
type Person = {
name: string
};
let person: Person
const employee = {
name: 'Anecdote',
job: 'Developer',
}
person = employee; // OK
employee
는 Person
타입에 필요한 name
속성을 가지고 있기 때문에 그 외의 속성이 있더라도 person
의 값으로 할당할 수 있다.
타입스크립트는 다른 인터페이스여도 이해할 수 있을만큼 영리하다.
interface Vector2D {
x: number;
y: number;
}
function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
interface NamedVector { // extends Vector2D로도 가능
name: string;
x: number;
y: number;
}
const v: NamedVector = { x: 3, y: 4, name: 'Zee' };
calculateLength(v); // 정상, 결과는 5
아이템 5: any 타입 지양하기
any 타입 사용시 타입 체커와 타입스크립트 언어 서비스를 무력화시킨다.
따라서 최대한 사용을 피할 것
- any 타입에는 타입 안정성이 없다.
age는 number 타입으로 선언되었지만, as any를 사용하면 string 타입을 할당할 수 있게 된다.
따라서 아래처럼 선언될 가능성이 있다.
ex. age += 1 // 런타임에 정상, age는 “121” - any 타입에는 언어 서비스가 적용되지 않는다.
=> ts 모토:확장 가능한 자바스크립트
타입이 있다면 타입스크립트 언어 서비스는 자동완성 기능과 적절한 도움말을 제공한다.
그러나 any 타입은 제공하지 않는다.
이름 변경 서비스도 제공하지 않는다.
interface Person {
first: string;
last: string;
}
const formatName = (p: Person) => `${p.first} ${p.last}`
const formatNameAny = (p: any) => `${p.first} ${p.last}`
--- 여기서 Rename Symbol을 클릭 해 이름 변경 ---
프로젝트 내의 심벌 이름이 모두 변경됨
3. any 타입은 코드 리팩터링할 때 버그를 감춘다.
4. any는 타입 설계를 감춰버린다.
5. any는 타입시스템의 신뢰도를 떨어뜨린다.
'Javascript & Typescript' 카테고리의 다른 글
[Typescript] 이펙티브타입스크립트 (#41 ~ #47) (2) | 2024.11.25 |
---|---|
[Typescript] 이펙티브타입스크립트 (#34 ~ #40) (0) | 2024.11.03 |
[javascript] forEach, map, filter, reduce 메서드 작동원리 (1) | 2023.03.02 |