TypeScript 기본-3

김정훈·2023년 7월 31일
0

void의 두 가지 사용법

  1. void 함수에는 return 값을 넣으면 안된다.( undefined는 가능, null은 불가능)
  2. 메서드, 매개변수가 void인 경우에는 return 값이 존재해도 된다.
    : void를 메서드나 매개변수로 사용하더라도 해당 변수 자체는 반환값을 나타내지 않는다.
    내부에서 호출하는 함수나 콜백 함수가 반환값을 가질 수 있다.
  3. 매개변수에서 쓰이는 void는 실제 return 값이 뭔지 신경쓰지 않겠다.
// Return값이 void
function a(): void{
	return undefined;
}

// 메서드가 void
interface Human{
	talk: () => void;
}
const human: Human = {
	talk() {return 'abc';}
}

// 매개변수가 void
function a(callback:()=> void): void{}
a(()=>{
	return 3;
});

declare을 사용하면 함수의 구현부를 안 만들고 Type만 정의해둘 수 있다.

deflare function forEach(arr: number[], callback: (e1:number) => void):void;

let target: number[] = [];
forEach([1,2,3], e1 => {target.push(e1)});
forEach([1,2,3], e1 => target.push(e1));

// + 강제 타입 변환
const test = a as unknown as number; // test는 number로 바꿔라 내가 책임진다?

unknown과 any(그리고 타입 대입가능표)

any는 타입 체크를 아예 포기하는 것.
unknown은 아직까지 타입이 확실하지 않아, 나중에 지정해서 쓸수있게끔 하는 것.

const a: A={
	talk() {return 3;}
}
const b: unknown = a.talk();
(b as A).talk();


타입 좁히기(타입 가드)

asunknown인 경우를 제외하고 가능하면 쓰지 않는 것이 좋다.

function numOrStr(a: number | string){
	if(typeof a === 'number'){
		a.toFixed(1);
	} else{
		a.charAt(3);	
	}
	if(typeof a === 'string'){
		a.charAt(3);
	}
}

배열

function numOrNumArray(a: number | number[]){
	if(Array.isArray(a)){
		a.concat(4);
	} else{
		a.toFixed(3);
	}
}

클래스

class typeA{
    aaa(){}
}
class typeB{
    bbb(){}
}
function aOrB(param: typeA | typeB){
// 여기서 typeA는 클래스 자체를 의미하는 것이 아니라 new typeA()을 의미한다.
	if(param instanceof typeA){
		param.aaa();
	}
}

값으로 구분(보통 이걸 사용)

type B = {type: 'b', bbb: string};
type C = {type: 'c', ccc: string};
type D = {type: 'd', ddd: string};

function typeCheck(a: B | C | D){
	if(a.type==='b'){
		a.bbb;
	} else if(a.type === 'c'){
		a.ccc;
	} else {
		a.ddd;
	}
}

속성으로 구분 : in 연산자를 사용

function typeCheck(a: B | C | D){
	if('bbb' in a){
		a.type;
	} else if('ccc' in a){
		a.ccc;
	} else {
		a.ddd;
	}
}

⭐️⭐️⭐️ 객체를 만들 때 type을 만드는 습관을 가지자.

const human = {type: 'human'}
const dog = {type:'dog'}
const cat = {type:'cat'}

커스텀 타입 가드(js, 형식 조건자)

타입가드
: 변수나 객체의 타입을 더 구체적으로 추론하기 위해 사용하는 개념

타입을 구분해주는 커스텀 함수를 직접 만들 수 있다.
return타입에 is가 들어가 있는 함수는 커스텀 타입 가드 함수이다.
어떨 때 쓰냐? if문 안에 써서 타입스크립트에게 정확한 타입을 가르쳐준다.

interface Cat { meow: number}
interface Dog { bow: number}
// a에 meow라는 고양이가 있다면 false;
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);
	}
}

{}와 Object , unknown

{}, Object : 모든 타입(객체를 뜻하는 것이 아님) + null,undefined는 제외한다.

unknown
unknown = {} | null | undefined

// 옛날 버전
const z: unknwon = 'hi';
if(z){
	z; // z: unknown
}
// 최신 버전
if(z){
	z; // z: {}
}

readonly, 인덱스드 시그니처, 맵드 타입스

readonly

interface A{
	readonly a: string;
}
const aaa: A = {a:'hello', b:'world'};
aaa.a = '123' // 여기서 오류난다. readonly속성이기 때문

인덱스드 시그니처

type A = {[key: string]: number}
const test: A = {a: 5, b: 3}

type B = 'Human' | 'Mammal' | 'Animal';
type Bc={[key in B]: number};
const testB: Bc = {Human:3};

// + interface에서는 |, &을 쓰지 못한다.

클래스의 새로운 기능들

// 원본
class A{
	a: string;
	b: number;
	constructor() {
		this.a = '123';
		this.b = 123;
	}
}

// 축약
class A{
	a:string='123';
	b:number=123;
}

// Constructor가 필요한 이유 : 이렇게 쓴다.
class A{
	a: string;
	b: number;
	constructor(a: string, b:number = 123) {
		this.a = a;
		this.b = b;
	}
}
const a = new A('123');

매개변수에 기본값이 있으면 ?(Optional Chaining)을 쓰지 않아도 된다.

여기서 A는 new A('123')(인스턴스)을 가리킨다.

type AA = A; 
const a: A = new A('123')

이건 클래스 자체인 A(본체?)를 가리킨다(typeof)

const b: typeof A = A;

implements : 인터페이스를 구현한다.

interface A{
	a: string;
	b: string;
}
class B implements A{
	a: string = '123';
	b: string = 'world';
}

클래스 내부에서만 사용가능한 private , protected
공통점 : new B()한 경우(인스턴스) 에서는 둘다 사용할 수 없다.
차이점 : 상속받았을 때 쓸수있냐 없냐

class B implements A{
	private a: string = '123'
	protected b: string = 'world';
}

class C extends B{
	method(){
		console.log(this.a); // 에러난다. 사용못함.
		console.log(this.b);
	}
}
publicprotectedprivate
클래스내부OOO
인스턴스(newA())OXX
상속클래스OOX

제네릭(Generic)

: 지금 타입은 모르겠는데, 나중에 정한다.
타입을 변수처럼 만드는 것이 Generic이다.

function add<T>(x: T, y:T): T{

}

function add2<T extends number, K extends string>(x:T, y:K): T{
	//이런 방식으로 여러 개의 Generic을 만들고 제한을 둘 수도 있다.
}
add2(1,"제네릭2");

function add3<T extends {a:string}>(x:T): T{ return x };
add3({a: 'hello'})

function add4<T extends string[]>(x:T): T{ return x };
add3(['1','2','3'])

//함수 모양의 제한
function add5<T extends (a:string) => number>(x:T): T{ return x };
add5((a) => +a);
profile
WebDeveloper

0개의 댓글