Closed moonheekim0118 closed 2 years ago
안 돼 희생하지마 😭 나 자신 먼저 지켜!
인덱스 시그니처가 number로 표현되어 있다면 입력한 값이 number여야 한다는 것을 의미하지만, 이는 순수 타입스크립트 코드다. 배열은 객체이므로 키는 숫자가 아니라 문자열이다. 그래서 실제 런타임에 사용되는 키는 strinig 타입이다.
타입스크립트는 객체의 숫자 키를 허용하고 문자열 키와 다른 것으로 인식한다. Array 타입 선언은 다음과 같다.
interface Array<T> {
// ...
}
만약 숫자를 사용하여 인덱스할 항목을 지정한다면, Array 또는 튜플 타입을 사용한다. 어떤 길이를 가지는 배열과 비슷한 형태의 튜플을 사용하고 싶다면, 타입스크립트의 ArrayLike 타입을 사용한다.
readonly
로 선언된 배열
readonly
키워드가 붙지 않은 배열(변경 가능한 배열)은 readonly
키워드가 붙은 배열의 서브타입이다. 따라서 변경 가능한 배열은 readonly
배열에 할당할 수 있다. 그 반대로 readonly
배열은 변경 가능한 배열에 할당할 수 없다.함수가 매개변수를 수정하지 않는다면 readonly
로 선언한다. 매개변수를 readonly로 선언하면 다음과 같은 일이 생긴다.
const와 readonly의 차이
const arr1: string[] = [];
// arr1 변수가 가리키는 배열을 변경할 수 없고,
// 배열 자체는 변경할 수 있다. (배열을 변경하는 메소드 호출 가능)
const arr2: readonly string[] = [];
// arr2 변수가 가리키는 배열을 변경할 수 없고,
// 배열 자체도 변경할 수 없다. (배열을 변경하는 메소드 호출 불가능)
let arr3: readonly string[] = [];
// arr3 변수가 가리키는 배열을 자유롭게 변경 가능.
// 그러나 배열 자체는 변경하지 못 한다. (배열을 변경하는 메소드 호출 불가능)
readonly
는 얕게 동작한다.
어떤 객체를 요소로 하는 readonly
배열이 있을 때, 그 요소인 객체 자체는 readonly
가 아니다.
(readonly string[])[]
: readonly string[]
의 변경 가능한 배열readonly string[][]
: 변경가능한 배열의 readonly 배열why?
interface Vector3 { x: number; y: number; z: number; };
function getComponent(vector: Vector3, axis: 'x' | 'y' | 'z') {
return vector[axis];
}
let x = 'x';
let vec = { x: 10, y: 20, z: 30 };
getComponent(vec, x) ;
// 런타임시 동작은 잘 되는데 편집기에서 아래와 같은 오류 나옴
// ~ 'string' 형식의 인수는 "x" | "y" | "z" 형식의 매개변수에 할당될 수 없습니다.
const v2 = {
x: 1 as const,
y: 2
}
// 타입은 { x: 1 ; y: number; }
const v3 = {
x: 1,
y: 2
} as const
// 타입은 { readonly x:1, readonly y:2 };
const el = document.getElementById('foo');
if(el){
el
el.innerHTML = ' wow '.blikc();
} else {
el
alert('No Element');
}
a in ab
네트워크 요청: 요청은 성공하거나 실패하겠지만, 성공한 동시에 실패할 수는 없다.
데이터베이스에서 특정 아이디를 갖는 컬럼을 쿼리: 해당 컬럼이 있거나 없지만, 있으면서 없을 수는 없다.
어떤 파일명을 갖는 파일 내용을 읽어오는 경우: 해당 파일이 있거나 없지만, 있으면서 없을 수는 없다.
// 사용자 정의 타입가드!
function isInputElement (el: HTMLElement): el is HTMLInputElement {
return 'value' in el;
}
function getElementContent(el: HTMLElement){
if(isInputElement(el){
return el.value;
}
}
function isDefined<T>(x: T | undefined) : x is T {
return x !== undefined;
}
typeof null === 'object'
타: 타입스크립트를 위해 스: 스스로를 희생하자
타입스크립트의 맣은 타입 구문은 사실 불필요하다.
비구조화 할당문은 모든 지역 변수의 타입이 추론되도록 한다.
타입스크립트의 변수의 타입은 일반적으로 처음 등장할 때 결정된다.
const elmo: Product = {
name: 'Elmo',
id: '123abc',
price: 28.99
}
interface Vector2D { x: number, y: number }
function add(a: Vector2D, b: Vector2D){
return {x: a.x + b.x, y: a.y+ b.y}
}
// { x:number, y: number}로 추론되어 Vector2D와 호환된다
// 입력 타입은 Vector2D인데 반환 타입은 number라 당황스러울 수 있다
변수의 값은 바뀔 수 있지만 그 타입은 보통 바뀌지 않는다.
유니온 타입으로 범위를 좁힐 수는 있지만 값을 사용할 때마다 타입을 확인하는 것보다는 별도의 변수를 도입하는 것이 좋다.
상수를 사용해서 변수를 초기화할 때 타입을 명시하지 않으면 타입 체커가 타입을 결정해야 한다. 즉, 정해진 값을 가지고 할당 가능한 값들의 집합을 유추해야 한다는 뜻이다. 이러한 과정을 넓히기(winding)이라고 부른다.
interface Vector2D { x: number, y: number }
function getComponent(vector: Vector2D, axis: 'x' | 'y'){
return vector[axis]
}
let x = 'x';
let vec = { x: 10, y: 20 };
getComponent(vec, x);
// string 형식의 인수는 'x' | 'y' 형식의 매개변수에 할당될 수 없습니다.
x의 타입은 할당 시점에 넓히기가 동작하여 string으로 추론되었다.
const x = 'x' // 타입이 'x'
const v: { x: 1|3|5 } = { x:1 }
명시적 타입 구문 제공
타입 체커에 추가적인 문잭을 제공(함수의 매개변수로 값을 전달)
const v = { x: 1, y: 2 } as const
// 타입 { readonly x: 1, readonly y: 2 }
const el = document.getElementById('foo');
if(el) { console.log('not null') }
else { console.log('null') }
function isInputElement(el: HTMLElement): el is HTMLInputElement {
return 'value' in el;
}
- Pick
- 제너릭 타입
- 중복된 코드를 없앤다는 관점으로, Pick을 사용하는 것은 함수를 호출하는 것에 비유할 수 있다
- T, K 두 가지 타입을 받아서 타입을 반환한다
```jsx
type Pick<T,K> = { [k in k]: T[k]};
K는 인덱스로 사용될 수 있는 값 , 실제 T의 키의 부분집합
```
- 중복되는 것을 피하는 방법
```jsx
interface SaveAction {
type: 'save';
}
interface LoadAction {
type: 'load';
}
type Action = SaveAction | LoadiAction;
type ActionType = 'save' | 'load';
-> 인덱싱을 통해서 중복 피하기
type ActionType = Action['type'];
-> Pick 활용하기
type ActionRec = Pick<Action, 'type'>; // {type: 'save' |'load'}
```
- 제너릭 타입은 타입을 위한 함수와 같다
- 제너릭 타입에서 매개변수를 제한할 수 있는 방법
- extends 이용 하면, 제너릭 매개변수가 특정 타입을 확장한다고 선언할 수 있다
```jsx
interface Name {
first: string;
last :string;
}
type DancingDuo<T extends Name> = [T,T];
const couple : DancingDuo<Name> = [
{first 'Fred', last: 'Astaire'}
]
```
자바스크립트 객체는 문자열 키를 타입의 값과 관계없이 매핑한다
type Rocket = {[prototype:string] : string};
const rocekt : Rocket = {
name : 'Falcon 9',
variant: 'v1.0',
}
인덱스 시그니처
키의 이름
키의 타입
값의 타입
단점
사용할 때
가능하다면 인덱스 시그니처 보다 인터페이스, Record, 매핑된 타입을 사용하기
자바스크립트의 암시적 타입 강제
객체란 키 / 값 쌍의 모임
타입스크립트는 숫자 키를 허용한다
타스로 2행시를 해보겠읍니다.
타 타인을 위해 스 스스로를 희생하자