function getElement(elOrId: string | HTMLElement | null): HTMLElement {
if (typeof elOrId === "object") {
return elOrId; // 'HTMLElement | null' 형식은 'HTMLElement' 형식에 할당할 수 없습니다.
}
}
typeof null
: "object"
이므로 elOrId는 여전히 null일 수 있는 것! HTMLElement를 반환해야하는 함수이기 때문에 에러가 남.declare function fetch(
input: RequestInfo, init?: RequestInit
) : Promise<Response>;
type RequestInfo = Request | String;
const x: never = 12; //error : '12' 형식은 'never'에 할당할 수 없습니다.
type A = 'A';
type B = 'B';
type Twelve = 12;
type AB = "A" | "B";
type AB12 = "A" | "B" | 12;
type AB12_2 = AB | 12;
const a: AB = "A";
const c: AB = "C"; //error
type Int = 1|2|3|4|5 // | ...
interface Identified {
id : string;
}
interface Person {
name : string;
}
interface Lifespan {
birth: Date;
death?: Date;
}
type PersonSpan = Person & Lifespan;
👉 Person과 Lifespan을 둘 다 가지는 값이 인터섹션 타입에 속함.
👉 두 속성을 모두 충족해야함.
const ps: PersonSpan = {
name: 'Alan Turing',
birth: new Date('1912/06/23'),
death: new Date('1954/06/07'),
};
✅ 결론 : Person과 Lifespan의 속성을 모두 가져야 한다.
interface Person {
name: string;
}
interface Lifespan {
birth: Date;
death?: Date;
}
type K = Person | Lifespan;
}
👉 Person 또는 Lifespan을 충족해야 함.
👉 두 가지 모두 충족도 가능.
const sh : K = {
name: "seohyun",
}
const sh : K = {
birth: new Date('2001/12/19')
}
const sh : K = {
name: "seohyun",
birth: new Date('2001/12/19')
}
✅ 결론 : Person의 속성 또는 Lifespan의 속성, 또는 두 interface에 있는 속성 모두를 가져야 한다.
interface Person {
name: string;
}
type Keyof_Person = keyof Person; //name
type K = keyof (Person | Lifespan) // 겹치는 속성이 없으므로 'never'
❗ 해석
keyof (A&B) = (keyof A) | (keyof B)
--> A&B 모두의 keyof이므로, A의 keyof와 B의 keyof의 합집합으로 해석되는 개념.
keyof (A|B) = (keyof A) & (keyof B)
--> A 또는 B의 keyof이므로, A의 keyof와 B의 keyof의 교집합으로 해석되는 개념.
✅ 결론 : keyof에서 & -> 합집합, | -> 교집합으로 반대 개념이라고 생각하면 된다.
interface Vector1D { x: number; }
interface Vector2D extends Vector1D { y: number; } // { x: number; y : number; }
interface Vector3D extends Vector2D { z: number; } // { x: number; y : number; z: number;}
function getKey<K extends string>(val: any, key: K) {
// ...
}
👉 K는 string을 상속한다 = string의 부분 집합 범위를 가지는 어떠한 타입이 된다
👉 string 리터럴 타입, string 리터럴 타입의 유니온, string 자신을 포함
// 파라미터 key가 파라미터 vals의 keyof를 타입으로 하는지 타입체크함.
function sortBy<K extends keyof T, T>(vals: T[], key: K): T[] {
vals.sort((a, b) => (a[key] === b[key] ? 0 : a[key] < b[key] ? -1 : +1));
return vals;
}
const pts: Point[] = [
{ x: 1, y: 1 },
{ x: 2, y: 0 },
];
// key(두번째 인자)는 "x" | "y" 이어야 함.
sortBy(pts, "x");
sortBy(pts, "y");
sortBy(pts, Math.random() < 0.5 ? "x" : "y");
sortBy(pts, "z"); //error
const list = [1, 2]; // 추론된 타입 : 무한개 있을 수 있는 number[]
const tuple: [number, number] = list; // error: list는 두개보다 더 적거나 많을 수 있기에 오류
[number, number]
는 number[]
의 부분집합이다.number[]
는 [number, number]
에 할당될 수 없다.const triple = [1, 2, 3];
const double: [number, number] = triple; //error : 'length' 속성의 형식이 호환되지 않습니다.
❓ 갑자기 왜 length 속성이 나왔을까?
👉 타입스크립트가 double에서 숫자의 쌍을 모델링할 때, { 0: number, 1: number, length: 2}
로 모델링하기 때문에 length값이 달라 오류!
type Exclude<T, U> = T extends U ? never : T
type T = Exclude<string | Date, string | number>; //왼쪽 타입에서 오른쪽 타입에 할당 가능한 타입을 배제한다. --> 타입은 Date
type NonZeroNums = Exclude<number, 0>; // 결과가 적절한 타입스크립트 타입일 때만 유효하기 때문에 --> 타입은 여전히 number
interface Cylinder { //타입
radius: number;
height: number;
}
const Cylinder = (radius: number, height: number) => ({ radius, height }); // 값
function calculateVolumee(shape: unknown) {
if (shape instanceof Cylinder) { //값
shape.radius; //error : 근데..값이 없는데?
}
}
👉 Cylinder 타입인지 체크하려고 했지만, instanceof
는 자바스크립트의 런타임 연산자로 값에 대해 연산을 함. 따라서 값으로 쓰임.
interface Personn {
first: string;
last: string;
}
const p: Person = { first: "Jane", last: "Jacobs" };
function email(p: Person, subject: string, body: string): Response {
//...
return new Response();
}
// 타입으로 읽음
type T1 = typeof p; // "Person"
type T2 = typeof email; //Type is (p:Person, subject:string, bodyLstring) => Response
// 값으로 읽음
const v1 = typeof p; // "object"
const v2 = typeof email; // "function"
typeof
=> "function"class Cylinder {
radius = 1;
height = 1;
}
// 값으로 읽음 -> JS에서 함수로 구현되므로
const v = typeof Cylinder; // "function"
// 타입으로 읽음
type T = typeof Cylinder; // T 타입 : "typeof Cylinder"
instance 인스턴스
instance(객체)는 class를 통해서 생성한 실체 입니다. 프로그램에서는 instance를 가지고 모두 조작을 하며, class를 가지고 조작을 하지 않습니다. 왜냐 하면 class는 개념 적인 것이고 instance가 실제이기 때문 입니다.
type T = Cylinder; // T 타입 : Cylinder
const a : T = new Cylinder();
또는 InstanceType 제너릭
을 사용해서생성자 함수(constructor function)를 타입을 인자로 받아, 해당 생성자 함수가 반환하는 인스턴스의 타입을 반환한다.
type C = InstanceType<typeof Cylinder>; // C 타입 : Cylinder
obj['field']
를 사용해야 한다.interface Person {
first: string;
last: string;
}
const first: Person["first"] = p["first"]; // 타입 : string
const firstt: Person["first"] = p.first; // 타입 : string
const firsttt: Person.first = p["first"]; // error
type PersonEl = Person["first" | "last"]; // 타입 : string
type Tuple = [string, number, Date];
type TupleEl = Tuple[number]; // 여기서 number가 0,1,2가 될 수 있으니까 --> 타입 : string| number | Date
interface Person {
first: string
last: string
}
function email(options: {person: Person; subject: string; body: string}) {
// ...
}
// error
function email ({person: Person; subject: string; body: string}) {
// ...
}
/** 해결 : 타입과 값 구분하기 */
function email ({person, subject, body} : {person: Person; subject: string; body: string}) {
// ...
}
✅ 결론 : 타입스크립트 코드를 읽을 때 타입인지 값인지 구분하는 방법을 터득해야 한다.