23.01.18 인터페이스&제네릭&타입추론

Gon·2023년 1월 18일
1
post-thumbnail

인터페이스

기본 정의

interface Person {
  name: string;
  age: number;
}

const person1: Person = { name: "John", age: 50 };
const person2: Person = { name: "Amy", age: 20 };

선택 속성

interface Person {
  name: string;
  age?: number; // ? 있으면 생략 가능
}

const person: Person = { name: "John" };

Read only 속성

interface Sports {
  readonly name: string;
  time?: number;
}

const sports: Sports = { name: "축구", time: 90 };
sports.name = "야구" // error

let readonlyArr: ReadonlyArray<number> = [1, 2, 3];
readOnlyArr.splice(0,1); // error
readOnlyArr.push(4); // error
readOnlyArr[0] = 100; // error

index type

interface Job {
  readonly name: string;
  [key: string]: string | number;
}

const job1: Job = { name: "Developer", pay: "secret", years: 3 };

함수 타입

interface Print {
  (name: string, age: number): string;
}

const getNameAndAge: Print = function (name, age) {
  return `name: ${name}, age: ${age}`;
};

인터페이스 확장

interface Korean extends Person {
  birth: "KOR"
}

interface Korean {
  name: string;
  age: number;
  birth: 'KOR';
}

interface Developer {
  job: 'developer';
}

interface KorAndDev extends Korean, Developer {}

interface KorAndDev {
  name: string;
  age: number;
  birth: 'KOR';
  job: 'developer';
}

intersection Type: 여러 타입을 모두 만족하는 하나의 타입

interface Person {
  name: string;
  age: number;
}

interface Developer {
  name: string;
  skill: string;
}

type DevJob = Person & Developer;

const nbcPerson: DevJob = {
  name: 'a',
  age: 20,
  skill: 'ts',
};

type vs interface

타입 별칭과 인터페이스의 가장 큰 차이점은 타입의 확장 가능 / 불가능 여부
type 보다는 interface로 선언해서 사용하는 것을 추천함


제네릭

제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것

function getText(text: any): any {
  return text;
}

getText('hi'); // 'hi'
getText(10); // 10
getText(true); // true
function getText<T>(text: T): T {
  return text;
}

getText<string>('hi');
getText<number>(10);
getText<boolean>(true);

추가 예시

function getItemArray<T>(arr: T[], index: number): T {
  return arr[index];
}

function pushItemArray<T>(arr: T[], item: T): void {
  arr.push(item);
}

const techStack = ["js", "react"];
const nums = [1, 2, 3, 4];

getItemArray(techStack, 0); // "js"
pushItemArray<string>(techStack, "ts"); // ["js", "react", "ts"]

getItemArray(nums, 0); // 1
pushItemArray(nums, 5); // [1, 2, 3, 4, 5]

제네릭 타입 변수

// before
function printOut<T>(input: T): T {
  console.log(input.length); // Error: T doesn't have .length
  return input;
}

// after
function printOut<T>(input: T[]): T[] {
  console.log(input.length);
  return input;
}

printOut([1, 2, 3]);

제네릭 제약 조건

// before
function printOut<T>(input: T): T {
  console.log(input.length); // Error: T doesn't have .length
  return input;
}

// after
interface LengthWise {
  length: number;
}

function printOut<T extends LengthWise>(input: T): T {
  console.log(input.length);
  return input;
}

// printOut(10); // Error, 숫자 타입에는 `length`가 존재하지 않으므로 오류 발생
// printOut({ length: 0, value: 'hi' }); // `input.length` 코드는 객체의 속성 접근과 같이 동작하므로 오류 없음

타입 추론

기본 타입 추론

let a = 123;
let b = 'abc';

a = 'abc'; // error 'string' 형식은 'number' 형식에 할당할 수 없습니다.
b = 123; // error 'number' 형식은 'string' 형식에 할당할 수 없습니다.

const c1 = 123;
const c2 = 'abc';

const arr = [1, 2, 3];
const [n1, n2, n3] = arr;
arr.push('a'); // error 'string' 형식의 인수는 'number' 형식의 매개 변수에 할당될 수 없습니다.

const obj = { numId: 1, stringId: '1' };
const { numId, stringId } = obj;
console.log(numId === stringId); // error 'number'이(가) 'string'과(와) 겹치지 않으므로 이 비교는 의도하지 않은 것 같습니다.

함수형 타입 추론

const func1 = (a = 'a', b = 1) => {
  return `${a} ${b};`;
};
func1(3, 6); // 'number' 형식의 인수는 'string' 형식의 매개 변수에 할당될 수 없습니다.

const v1: number = func1('a', 1); // 'string' 형식은 'number' 형식에 할당할 수 없습니다.

const func2 = (value: number) => {
  if (value < 10) {
    return value;
  } else {
    return `${value} is big`;
  }
};

0개의 댓글