타입스크립트

타입스크립트


함수타입

// Call Signature: (a:number, b:number) => number
function add(a : number, b: number) {
   return a + b;
}

add(1);
//Error : Expected 2 arguments, but got 1.
add(1, 2); // Ok
add(1, 2, 3);
//Error : Expected 2 arguments, but got 3.
  • 타입스크립트는 함수에 선언된 모든 매개변수가 필수라고 가정한다!

const introduce = (name:string, 
height?:number) => { //?는 옵셔널파라미터 있어도되고 없어도 되고
   console.log(`이름 : ${name}`);
   console.log(`키 : ${height + 10}`)
//Error : 'height' is possibly 'undefined'.
}

introduce("김현준"); // OK
introduce("김현준", undefined); // OK
introduce("김현준", 170); // OK
  • 함수 호출에 선택적 매개변수를 인수로 제공할 필요 X
    선택적 매개변수에는 항상 | undefined 가
    유니언타입으로 추가 되어있기 때문!
  • 선택적 매개변수는 끝에 위치해야함

const introduce2 = (name:string, 
height : number|undefined ) => {
   console.log(`이름 : ${name}`);
if(typeof height === 'number'){
   	console.log(`키 : ${height + 10}`)   
 	}
}

introduce2("김현준"); // Error : Expected 2 arguments, but got 1.
introduce2("김현준", undefined); // OK
introduce2("김현준", 170); // OK

  • 선택적 매개변수는 | undefined를 포함하는 유니언 타입 매개변수와 다름.
    ?으로 표시된 선택적 매개변수가 아닌 매개변수는
    값이 명시적으로 undefined 일지라도 항상 제공되어야 한다.

const getSum = (...rest: number[]) =>{
//rest로 여러개의 넘버를 받음(넘버만!)

const getSum2 = (a: number,...rest:[number, number]) =>{
//튜플로 rest로 두개의 넘버를 받음

function singSongRecursive(songs : string[], count = 0) : number {
    return songs.length ? singSongRecursive(songs.slice(1), count + 1) : count;
}
// 재귀함수에서의 명시적 반환 타입지정
let singer : (song : string) => string;

singer = function(song) {
    // song : string의 타입
    return `Singing : ${song.toUpperCase()}!`; // OK
}
//타입 스크립트는 선언된 타입의 위치에 제공된 함수의 매개변수 타입을 유추할 수 있다!

void 반환타입

function logSong(song : string) : void {
  if(!song){
    return; // OK!  return undefined; 도 OK!
  }
  console.log(`${song}`);

  return true;   // Error! - Type 'boolean' is not assignable to type 'void'.
}
//  ← void를 반환하도록 선언되었으므로 값 반환을 허용하지 않음.

// But, 다음과 같이 화살표 함수는 구문 오류 없음!


type VoidReturn = () => void;
const test2:VoidReturn = () => 11;  // OK!
test2().toString(); // ?
//일부 함수는 어떤 값도 반환하지 않을 수 있음 -> 타입스크립트는 void 키워드를 사용해 반환값이 없는 함수의 타입을 확인할 수 있음
//void는 그냥 반환을 하려해도 타입스크립트는 검사를 안한다

//fuction은 등록을 해야해서 void를 썻는데 return이 있으면 오류뜨고
//화살표함수는 이미 등록이라서 void인데 return이 있어도 ㅇㅋ

never 반환타입

never 반환 함수는 (의도적으로) 항상 오류를 발생시키거나 무한 루프를 실행하는 함수

function fail(message : string) : never {
    throw new Error(`Invariant Failure : ${message}`);
    // JS는 return undefined; 가 생략
}

function workWithUnsafeParam(param : unknown){
    if(typeof param !== "string"){
        fail(`param should be a string, not ${typeof param}`);
    }

    // 여기에서 param의 타입은 string으로 알려짐
    param.toUpperCase();
}

함수 오버로드

동일한 이름에 매개 변수만 다른 여러 버전의 함수를 만드는 것
매개변수의 형태가 다양한 여러 케이스에 대응하는 같은 이름을 가진 함수를 만드는 것

// 서로 다른 버전의 함수들(선언부) -> `오버로드 시그니처`
function func(a : number): void;
function func(a : number, b : number, c : number) : void;

// 실제 구현부 -> `구현 시그니처`
function func(a:number, b?: number, c?:number) {
  if(typeof b === 'number' && typeof c === 'number') {
    console.log(a + b + c);
  } else {
    console.log(a * 20);
  }
}

func(1);
func(1,2,3);

this

동일한 이름에 매개 변수만 다른 여러 버전의 함수를 만드는 것
매개변수의 형태가 다양한 여러 케이스에 대응하는 같은 이름을 가진 함수를 만드는 것

function f(cb: (this: void) => number) {
    return cb();
}
// 이 함수 f는 콜백 함수 cb를 매개변수로 받고 있는데, cb는 this를 사용하지 않는 함수여야 한다는 것을 명시하고 있습니다. 이를 위해 cb의 타입으로 (this: void) => number를 지정했는데, 이는 this가 void 타입임을 나타냅니다. 즉, this를 사용하지 않는 함수여야 한다는 뜻입니다.

const obj = { id: 1 };

function x(this: typeof obj) {
    return this.id;
}

function y() {
    return 1;
}

f(x); // Fail
f(y); // OK


// f(x):
// 실패하는 이유는 x 함수가 this로 obj를 필요로 하지만, f 함수는 cb의 this가 void라고 명시했기 때문입니다. 즉, f는 this를 사용하지 않는 함수만 받을 수 있는데, x는 this를 사용하므로 타입 호환이 되지 않습니다.
// 오류 메시지에서 설명하듯이, void 타입의 this는 { id: number }와 호환되지 않습니다.

// f(y):
// 성공하는 이유는 y 함수는 this를 사용하지 않으므로, this: void로 선언된 콜백 함수로 사용할 수 있기 때문입니다.

Tip. tsconfig.json 에서 strict: true 가 포함하는 옵션들

{
  "strict": true,
  "strictNullChecks": true,
  "strictFunctionTypes": true,
  "strictBindCallApply": true,
  "strictPropertyInitialization": true,
  "noImplicitThis": true,
  "alwaysStrict": true,
}
//
noUncheckedIndexedAccess : 해당 index의 값이 undefined일  있음을 체크하겠다!
 옵션을 true로 설정하면 인덱스 시그니처에 'undefined' 포함시킨다!

결합

  1. concat을 이용한 결합
const nums1 = [1, 2, 3, 4, 5];
const nums2 = [10, 20, 30, 40, 50];

const result1 = nums1.concat(nums2);
// 당연히 result1은 number[]

const strings1 = ['lim', 'eun', 'ha'];
const result2 = result1.concat(strings1);// 에러가 뜬다. concat은 결합할 것의 타입이 같아야함
  1. spread를 이용한 결합
const nums1 = [1, 2, 3, 4, 5];
const nums2 = [10, 20, 30, 40, 50];

const result1 = nums1.concat(nums2);
// 당연히 result1은 number[]

const strings1 = ['lim', 'eun', 'ha'];
const result2 = [...result1, strings1];

// 둘을 결합한 result2는 ?? (string | number)[]

튜플

  • 고정된 크기의 배열. 각 인덱스에 알려진 특정 타입을 갖는다! 즉) 자리수가 고정이 튜플인것이다.
  • 튜플 타입은 가변 길이의 배열보다 더 구체적이다! 따라서, 배열은 튜플 타입의 변수에 할당할 수 없다.
  • 타입스크립트는 튜플의 길이를 알고있다. 따라서 길이가 다른 튜플은 서로 할당할 수 없다!
  • 인수에 배열 스프레드를 사용한 경우 해당 함수는 나머지 매개변수가 꼭 있어야 한다. 나머지 매개변수가 없다면 배열을 전달할 경우 반드시 튜플만 스프레드하여 전달할 수 있다! /** 함수의 매개변수 튜플

인터페이스

타입스크립트에서 인터페이스(interface)는 객체의 구조를 정의하는 데 사용되는 일종의 계약(Contract)입니다. 인터페이스는 객체가 어떤 속성을 가져야 하는지, 그리고 그 속성들이 어떤 타입이어야 하는지를 명시합니다.

interface User {
    id: number;
    name: string;
    age?: number; // 선택적 속성 (optional property)
}

let user1: User = {
    id: 1,
    name: "Alice"
};

let user2: User = {
    id: 2,
    name: "Bob",
    age: 30
};

//

interface Greet {
    (name: string): string;
}

const greetUser: Greet = (name: string) => {
    return `Hello, ${name}`;
};

console.log(greetUser("Alice")); // 출력: Hello, Alice

숫자 인덱스 시그니처(경력자 질문으로 많이 물어본다)

ppt 106p

왜 오류가 날까?
넘버가 통과를 못해서? 어떻게 해결을 할까?

###