const a: number = 5;
function add(x: number, y: number): number { return x + y }
const add: (x: number, y: number) => number = (x, y) => x + y;
const obj: { lat: number, lon: number } = { lat: 37.5, lon: 127.5 };
type Add =(x:number,y:number) => number
const add:Add=(x,y) => x+y
interface Add{
(x:number,y:number):number
}
const add: Add = (x,y) => x+y
튜플이란 ? 길이가 고정된 배열
let arr: string[] = [];
let arr2: Array<string> = [];
function rest(...args: string[]) {}
const tuple: [string, number] = ['1', 1];
tuple[2] = 'hello';
tuple.push('hello');
const의 경우 바뀔 일이 없어 고정된 원시값으로 타이핑을 하여
정확한 타입을 기입 가능
const a: true =true;
const b: 5 = 5;
const b = 6 //error
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
//Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
// 수정
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);
앞의 타입을 강제로 다른 타입으로 바꿈
가급적 비사용을 추천
const aa =123
aa= 'hello' as unknown as number
never관련 좋은 글
빈 배열은 never[]로 나오는데 이 경우 아무것도 넣을 수 없다.
null 또는 undefined가 아님을 개발자가 보증한다. 라는 의미로 보면된다
const head = document.querySelector('#head')!;
console.log(head);
const head = document.querySelector('#head');
if (head) {
console.log(head);
}
type World = 'world';
type Greeting = `hello ${World}`;
Key만 뽑아내고 싶다 ? keyof
자바스크립트 원형을 타입으로 쓰고 싶다? typeof
const obj = {a:'123',b:'hello',c:'world'};
type Key = keyof typeof obj // 'a'|'b'|'c'
type Value = typeof obj[keyof typeof obj] // '123'|'hello'|'world'
union|
은 'or' , ||
의 의미와 같고 (하나라도 있으면 된다)
intersection&
은 'and' &&
의 의미와 같다. (모든 속성이 있어야한다)
function add(x:string | number, y:string| number):string | number {return x+ y}
add(1,2)
add('1','2')
add(1,'2')
단, 타입은 모든 경우의 수를 다 고려하기 때문에
위의 경우 x:string y:number와 같은 경우 까지 고려한다.
type Animal = {breath :true};
type Mammal = Animal & {breed:true};
type Human = Mammal & {think :true};
const a: Human ={breath:true, breed:true,think:true}
interface A {
breath:true
}
interface B extends A {
breed:true
}
const b: B ={breat:true, breed:true}
interface는 재선언이 가능하며,
재 선언시 기존 타입과 합쳐진다.
이 특징을 기반으로 다른 사람의 라이브러리 코드를 수정하여 사용할 수 도 있다.
type A = string | number
type B = string
위 코드 중 type A가 type B에 비하여 더 넓은 타입을 가진다.
좁은타입에서 넓은 타입으로는 대입이 가능하지만,
넓은타입에서 좁은 타입으로는 대입이 불가능하다.
type A = {name:string};
type B = {age:number};
type C = {name:string, age:number}; // A & B
위의 경우는 type C가 가장 좁은 타입이다.
쉽게 말해 더 구체적일 수록 좁은 타입이다.
구조적 서브타이핑은 상위와 하위의 개념으로, 상위의 개념이 하위를 포함하고 있는 것이다.
구조적 서브타이핑에서는 하위가 다른 어떤 프로퍼티를 가지고 있는지 보단,
그저 상위의 프로터미만 가지고 있으면 된다.
하지만 잉여 속성 체크는 그에 반해 상위에 없는 프로퍼티를 가지면 에러를 발생시킨다.
이 둘의 발동 조건은 바로 객체 리터럴을 사용하냐, 안하냐의 차이다.
//잉여 속성 체크
interface A { a:string }
const obj1: A ={a: 'hello' b:'world'}. // error
// 구조적 서브 타이핑
const obj ={a: 'hello' b:'world'}
const obj1: A = obj //에러안남
void 타입은 return 값을 사용하지 않겠다 라는 뜻이다.
하지만 메서드나 매개변수에서는 리턴값이 사용이 가능하다.
function a(callback:()=>void): void {
return '3' //error
return undefined //pass
return null /error
}
a(() => {
return '3'
})
interface Human {
talk:()=>void;
}
const human:Human = {
talk() {retrun 'abc'}
}
any는 모든 타입이 다 가능하며, 타입검사를 포기한다고 보면 될듯하고
unknown 은 지금은 타입을 잘 모르겠지만, 추후에 지정을 하겠다 라고 생각하시면 편합니다.
초록색 체크도 x 로 보시면 됩니다.
function numOrStr(a: number | string) {
if (typeof a === 'string') {
a.split(',');
} else {
a.toFixed(1);
}
}
function numOrNumArr(a: number | number[]) {
if (Array.isArray(a)) {
a.slice(1);
} else {
a.toFixed(1);
}
}
type B = { type: 'b', bbb: string };
type C = { type: 'c', ccc: string };
type D = { type: 'd', ddd: string };
type A = B | C | D;
function typeCheck(a: A) {
if (a.type === 'b') {
a.bbb;
} else if (a.type === 'c') {
a.ccc;
} else {
a.ddd;
}
is를 활용하면 타입을 구분해주는 커스텀 함수를 직접 만들 수 있습니다.
interface Cat { meow:number }
interface Dog { bow: number }
function catOrDog (a: Cat | Dog) : a is Dog{
// 타입 판별
if((a as Cat).meow) { return false }
return true;
}
function pet(a: Cat | Dog){
if(catOrDog(a)){
console.log(a.bow)
}
if('meow' in a){
console.log(a.meow)
}
}
const isRejected = (input: PromiseSettledResult<unknown>): input is PromiseRejectedResult => { return input.status === 'rejected'};
const isFulfilled = <T>(input: PromiseSettledResult<T>): input is PromiseFulfilledResult<T> =>{ return input.status === 'fulfilled' } ;
const promises = await Promise.allSettled([Promise.resolve('a'), Promise.resolve('b')]);
const errors = promises.filter(isRejected);
class 또한 타입으로 사용할 수 있다
단, 주의사항은 이 경우 클래스 자체가 아니라 인스턴스를 의미한다
클래스 자체의 타입은 type of 클래스 이다.
class A {
aa() { }
}
class B {
bb() { }
}
function aOrB(para: A|B){
if(param instanceof A){
param.aa();
}
}
aOrB(A) //error
aOr(new B())
interface A {
readonly a: string;
b: string;
}
class B implements A {
private a: string = '123';
protectd b: string = '456';
c: string='wow';
method(){ // 모두 가능
console.log(this.a);
console.log(this.b);
console.log(this.c);
}
}
class C extneds B {
method(){
console.log(this.a); // 불가능
console.log(this.b);
console.log(this.c);
}
}
new C().a; // 접근 불가
new C().b; // 접근 불가
new C().c; // 접근 가능
public | protected | private | |
---|---|---|---|
클래스 내부 | 가능 | 가능 | 가능 |
인스턴스 | 가능 | 불가능 | 불가능 |
상속 클래스 | 가능 | 가능 | 불가능 |
단, 자바스크립트로 변환시 모두 사라지게된다.
readonly는 말 그대로 읽기 전용 속성이라 속성이 바뀌는것을 막을 수 있다.
inteface A {
readonly a: string;
b: string;
}
const aa :A {a:'hello' ,b: 'world'};
aa.a = '123' //error
어떤 값 , 수 이든 상관없이 전부 특정 타입이길 원할 때
type A = { [key: string] : number }
type B ='Human'|'Mammal'|'Animal'
type A = { [key in B] : number }
function abc (a:number, b?:number, c?:number){ }
abc(1)
abc(1,2)
abc(1,2,3)
abc(1,2,3,4)//error
제네릭은 타입에 대한 함수라고 생각하면 된다.
function add<T>(x: T, y: T): T { return x + y }
add<number>(1, 2);
add(1, 2);
add<string>('1', '2');
add('1', '2');
add(1, '2'); // error