본문 바로가기
코딩(개발)/Next.js

타입스크립트

by 플랜데버 2025. 1. 27.

TypeScript의 데이터 타입

 

변수타입정의

const 변수명:타입 = 기본값 ;

let 변수명:타입 = 기본값 ;

 

기본 타입 (Primitive Types)

ㄴ string , number, boolean, null, undefined, bigint , symbol

숫자  let age:number = 30;
문자  let name:string = 'bob';
boolean  let isAdult:boolean = true;
null  let a:null = null ;
undefined  let b:undefined = undefined ;

 


객체 타입 ( Object Types )

ㄴ object, Array<T>, Tuple, enum

 

1) object  : 객체 타입을 직접 정의

let person: { name: string; age: number } = { name: "Alice", age: 25 };

2)  Array : 배열

숫자형 배열  let a:number[] = [1,2,3];
숫자형 배열  let a2:Array<number> = [1,2,3];
문자형 배열  let week1:string[] = ["mon","tue","wed"];
문자형 배열  let week2:Array<number> = [ "mon","tue","wed" ];

 

3) Tuple : 인덱스 별로 타입이 다를때 사용 가능( 튜플은 고정된 길이와 타입을 가진 배열 )

let b:[string , number] ;

b = ['z' , 1];    ---> 가능

b = [1 , 'z' ];    ---> 불가능

 

4) enum : 값들의 집합을 미리 정의하고, 그 값들에 이름을 붙여 사용하는 자료형.

enum의 각 값은 기본적으로 숫자로 표현되며, 첫 번째 값은 0부터 시작하여 1씩 증가

 

기본 정의

enum  Os {

           Window,

           Ios,

           Android

}

 

let myOs : Os = Os.Window;

console.log(myOs);  // 출력: 0

 

숫자값 정의

enum  Os {

           Window = 1 ,

           Ios,

           Android = 10

}

Ios 는 자동으로 2 가 들어감.

 

문자값 정의

enum  Os {

           Window = 'ms',

           Ios,                --> 에러, 값을 넣으라고 나옴

           Android = 'google'

}

문자는 자동 증가 없음

 

문자 숫자 섞어서 쓸수 있음

enum  Os {

           Window = 'ms',

           Ios = 1,                --> 숫자 섞어서 쓸수 있음

           Android = 'google'

}

 


함수 타입( Function Types )

1) 함수 선언 시 타입지정

function  Add{

   (인자값 : 인자값 데이터 타입 , 인자값 인자값 데이터 타입 ) : 반환할 데이터 타입 (return 미사용시 void);

}

function Add (num1 : number, num2:number) : number {
   return num1 + num2;
}

const result = add(10,20);
console.log(result);

 

2) 함수 타입 표현식

let multiply: (x: number, y: number) => number;
multiply = (a, b) => a * b;

 

 

3) 옵셔널 매개변수

 

function hello(name? : string){            ⓛ 

   return `Hello, ${name || "world"}`;  

}
 
const result = hello();  → 에러 발생, 인자값 넣어줘야 함. 안넣어주고 싶을때는  name? 추가 해야함. 
const result2 = hello("amellia");
 
?를 넣을 경우 Hello world 이거나, Hello amellia 출력.
 
 

 ※ 선택적 매개변수를 앞에 넣으면 안됨.

function hello(name : string , age? : number) : string{   

     if(age !== undefined){
         return `Hello, ${name}. You are ${age}.`;  
    }else {
         return `Hello, ${name}.`;  
    }

}

console.log(hello("Amellia"));
console.log(hello("Amellia",30));

 

 

※ 꼭 앞에 넣고 싶다면 age? 대신 | 연산자 사용하여 구현.

function hello(age : number | undefined , name : string) : string{   ................ 생략 }

console.log(hello(undefined,"Amellia"));

 

 

4) 기본 매개변수

function hello(name = "world" ){            ⓛ  default 값을 지정해 줄 수도 있음. 

   return `Hello, ${name}`;  

}

 

 

5) 나머지 매개변수(rest parameter)

 

레스트 파라미터는 함수의 매개변수로 전달된 "나머지 인자들을 배열로 모아주는 문법"

주로 함수에 전달되는 가변 길이의 인자를 처리할 때 사용된다.

레스트 파라미터는 **...(spread 연산자)**를 사용하여 선언되며, 매개변수 목록의 마지막에 위치해야 한다.

레스트 파라미터는 없거나, 하나만 존재할 수 있다.

 

function add(...nums : number[ ]) : number {      → 타입을 배열로 정의 한다.

    return nums.reduce((result, num) => result + num, 0);  
}
ex1)
add(1,2,3);   // 결과는 6
add(1,2,3,4,5,6,7,8,9,10); // 결과는 55
 
 
ex2) 
function greet(greeting, ...names) {
  return `${greeting}, ${names.join(", ")}!`;
}

console.log(greet("Hello", "Alice", "Bob", "Charlie"));
// 출력: "Hello, Alice, Bob, Charlie!"

 


특별한 타입 (Special Types)

1) any : 아무 타입이나 허용

ㄴ any 타입을 사용하면 어떤 값이든 할당할 수 있으며, 타입 검사 없이 사용할 수 있다.

 

ex)
let anything: any = 5;
anything = "Hello";
anything = true;

 

2) unknown (안전한 any)

ㄴ any와 유사하지만, 직접 사용하려면 타입 검사를 해야 합니다.

 

ex)

let value: unknown;
value = "Hello";
if (typeof value === "string") {
    console.log(value.length);
}
// 5 출력됨

 

 

3) void : 함수에서 아무것도 반환하지 않을때 사용

funciton sayHello():void{

     console.log('hello') ;

                                             -----> return  없음

}

 

4) never : 항상에러를 반환하거나 영원히 끝나지 않는 함수의 타입으로 사용

 

funciton showError():never{

    funciton new Error();

}

 

funciton infLoop():never{

    while (true) {

          // do something..

    }

}


유니언(Union) 및 인터섹션(Intersection) 타입

1) 유니언 타입: 변수에 여러 타입을 할당할 수 있다. | ( or 를 의미)

 

▼ 변수 예시

let value: string | number;
value = "Hello";
value = 42;

 

  인터페이스 예시

interface Car{
    name : "car";
    color : string;
    start(): void;

}

interface Mobile{
    name : "mobile";
    color : string;
    call(): void;
}

function getGift(gift: Car | Mobile){
    console.log(gift.name);
    if(gift.name === "car"){
        gift.start();
    }else{
        gift.call();
    }
}


// `Car` 타입 객체 생성
const myCar: Car = {
  name: "car",
  color: "red",
  start() {
    console.log("The car is starting!");
  },
};

// `Mobile` 타입 객체 생성
const myMobile: Mobile = {
  name: "mobile",
  color: "blue",
  call() {
    console.log("Calling someone!");
  },
};

// 함수 호출
getGift(myCar);    // car, The car is starting!
getGift(myMobile); // mobile, Calling someone!
 

2) 인터섹션 타입 : & ( and 를 의미함 )

 

interface Car{
    name: string;
    start(): void;
}

interface Toy{
    name: string;
    color: string;
    price: number;
}

const toyCar : Toy & Car={
    name:"타요",
    start(){},                        Car와 Toy에 정의된 프로퍼티를 모두 작성해줘야 함.
    color: "blue",
    price:1000,
};

//1. 바로 사용
console.log(toyCar.name);  // 출력: "타요"
console.log(toyCar.color); // 출력: "blue"
console.log(toyCar.price); // 출력: 1000
toyCar.start();            // start 메서드 실행

//2. 함수 만들어서 사용
function describeToyCar(toyCar: Toy & Car) {
    console.log(`This toy car is named ${toyCar.name}.`);
    console.log(`Color: ${toyCar.color}, Price: ${toyCar.price}`);
    toyCar.start();
}

describeToyCar(toyCar);

///

 


타입 별칭 과 인터페이스

타입별칭과 인터페이스 공통점

 

  • 둘 다 객체 타입을 정의할 수 있습니다.
  • 둘 다 **확장(Extensibility)**이 가능합니다.
  • 코드의 타입 안전성을 보장합니다.

 

// 타입 별칭
type UserType = {
    id: number;
    name: string;
};

// 인터페이스
interface UserInterface {
    id: number;
    name: string;
}

const user1: UserType = { id: 1, name: "Alice" };
const user2: UserInterface = { id: 2, name: "Bob" };
 
 
 

타입 별칭과 인터페이스 차이

특징 타입별칭 인터페이스
1.정의 가능한 타입 객체, 유니언, 함수, 기본 타입 등 모두 정의 가능 객체 타입만 정의 가능
2. 확장 방식 인터섹션(&) 사용 extends 키워드 사용
3. 선언 병합 불가능 가능
4. 클래스와의 호환성 클래스로 구현 불가능 클래스로 구현 가능 (implements)
5. 유니언 타입 지원 지원 지원하지 않음

 

1) 정의 가능한 타입

  • type: 모든 타입(객체, 유니언, 함수, 프리미티브 등)을 정의할 수 있음.
  • interface: 객체 타입만 정의 가능.

▼ ex

1-1 유니언 타입

// 타입 별칭
type ID = string | number;

// 인터페이스 (불가능)
// interface ID = string | number; // 에러
 

1-2 함수타입

// 타입 별칭
type Add = (a: number, b: number) => number;

// 인터페이스
interface Add {
    (a: number, b: number): number;
}

2) 확장 방식

  • type: **인터섹션(&)**을 사용해 확장.
  • interface: extends 키워드를 사용해 확장
타입 별칭 확장
 
type Person = {
    name: string;
};

type Employee = Person & {
    jobTitle: string;
};

const employee: Employee = { name: "Alice", jobTitle: "Developer" };
인터페이스 확장
interface Person {
    name: string;
}

interface Employee extends Person {
    jobTitle: string;
}

const employee: Employee = { name: "Alice", jobTitle: "Developer" };

3) 선언 병합 (Declaration Merging)

  • type: 동일 이름의 타입을 여러 번 선언할 수 없습니다.
  • interface: 동일 이름의 인터페이스를 여러 번 선언하면 자동으로 병합됩니다.
 

 타입 별칭 병합 : 불가

type Person = {
    name: string;
};

// 다시 선언하면 에러 발생
// type Person = { age: number }; // 에러: 동일 이름의 타입 재선언 불가

 

인터페이스 병합 : 가능

interface Person {
    name: string;
}

interface Person {
    age: number;
}

const person: Person = { name: "Alice", age: 25 }; // 병합된 구조

 

 

4) 클래스에서 구현

  • **type**은 클래스를 통해 구현할 수 없습니다.
  • **interface** implements 키워드를 사용해 클래스에서 구현할 수 있습니다.
 타입 별칭 : 불가
 
type Animal = {
    name: string;
    speak(): void;
};

// class Dog implements Animal { ... } // 에러 발생

 

 인터페이스 : 가능

interface Animal {
    name: string;
    speak(): void;
}

class Dog implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log("Woof!");
    }
}

 

5) 유니언과 교차 타입

  • type: 유니언 타입(|)과 인터섹션 타입(&)을 정의할 수 있습니다.
  • interface: 유니언 타입을 직접 정의할 수 없습니다.
type Vehicle = { wheels: number } | { wings: number };

const car: Vehicle = { wheels: 4 }; // 가능
const plane: Vehicle = { wings: 2 }; // 가능

// 인터페이스로 유니언 타입은 정의할 수 없음
// interface Vehicle = { wheels: number } | { wings: number }; // 에러

 

 

언제 type과 interface를 사용할까?

1) interface를 사용하는 경우

  • 객체 타입 정의가 주목적인 경우.
  • 클래스와 함께 사용할 때 (예: implements 키워드).
  • 선언 병합이 필요한 경우.

2) type을 사용하는 경우

  • 유니언 타입이나 교차 타입이 필요한 경우.
  • 함수 타입을 정의할 때.
  • 복잡한 타입 조합이 필요한 경우.

**객체 타입을 정의할 때는 interface**를, **다양한 타입 정의가 필요할 때는 type**을 사용하는 것이 일반적


타입 별칭 

type 타입이름 = 타입정의;

type ID = string | number;
let userId: ID = "user123";

 

// 복잡한 객체 타입을 별칭으로 정의
type User = {
    id: number;
    name: string;
    age: number;
    isActive: boolean;
};

// 여러 곳에서 재사용
const user1: User = { id: 1, name: "Alice", age: 30, isActive: true };
const user2: User = { id: 2, name: "Bob", age: 25, isActive: false };

인테페이스 

객체의 속성에 접근하고 싶을 때 사용, object로 선언한 객체에는 접근이 불가

 

let  user:object ;

user = {

    name : 'xx';

    age : 30

}

 

console.log(user.name)  --->  name 에러남  ⓛ

user: object로 선언하면 user 변수는 "객체"임을 보장하지만 

object 타입은 객체의 구조를 알 수 없는 일반적인 타입이기 때문에, 객체의 속성에 직접 접근할 수 없음.

 

interface User{

   name : string ;

   age : number ;

}

 

let user : User = {

     name : 'xx';     --> 위에 정의된 두가지 값(name,age)을 모두 써줘야 함.

     age : 30

}

console.log(user.name)  --->  ⓛ 에러 해결되어 에러 안남.

user.age = 30; ---> 값 변경 가능.

user.gender = "mail";    --> 에러남  ②

 

 

◈ Optional Property

 

interface User{

   name : string ;

    age : number ;

    gender? : string ;   → 사용해도 되고 않해도 될때 ? 를 추가한다

}

 

let user : User = {

     name : 'xx';    위에 정의된 두가지 값을 모두 써줘야 함.

     age : 30

                             gender 값을 설정하지 않아도...

}

 

user.gender = "mail";    -   에러 해결되어 에러 안남

 

◈ ReadOnly Property

interface User{

   name : string ;

   age : number ;

   gender? : string ;   

   readonly birthYear : number ;  → 수정불가하게 할때 사용.

}

 

let user : User = {

     name : 'xx';    

     age : 30

     birthYear : 2000,    최초 할당은 가능

}

 

user.birthYaer = 1990 ;     이후 수정 불가! 재할당 시 에러남.

 

 

 

◈ 문자열 인덱스 :   옵셔널 프로퍼티가 여러개 일때 

 

interface User{

   name : string ;

   age : number ;

   gender? : string ;   

   readonly birthYear : number ;

   [grade : number] : string ;    → number 형의 key , string 형의 값

}

 

let user : User = {

     name : 'xx';    

     age : 30

     birthYear : 2000, 

     1 :  'A' ,

     2 :  'B' ,

}

 

◈ 문자열 인덱스 :   옵셔널 프로퍼티 의 범위 축소

type Score = 'A' | 'B' |  'C' |  'D' ;  범위를 축소

 

interface User{

   name : string ;

   age : number ;

   gender? : string ;   

   readonly birthYear : number ;

   [grade :number]: string  string 형은 너무 광범위 함

[grade : number] : Score ;   Score 에 정의된 범위 내의 값으로만 지정 해야함

}

 

let user : User = {

     name : 'xx';    

     age : 30

     birthYear : 2000, 

     1 :  'A' ,

     2 :  'B' ,

     3 :  'Z'   Score 에 정의된 범위 내의 값이 아니므로 에러남.

}

 

◈ interface 로 함수 정의 

 

interface  Add{

   (인자값 : 인자값 데이터 타입 , 인자값 인자값 데이터 타입 ) : 반환할 데이터 타입;

}

 

ex)

interface  Add{

   (num1 : number  , num2 : number ) : number ;

}

 

const  add : Add  = function(num1 , num2){    

      return num1 + num2;

}  

add(10,20);   

 

ex2) 화살표 함수 이용.

interface  

IsAdult

{

   (age: number ) : boolean ;

}

 

const  a: IsAdult = (age) =>{    

      return age > 19;

} 

 

a(33);

 

◈ interface 로 클래스 정의 

//implements

interface  Car   {

    color : string ;

    wheels : number ;

    start() : void ;

}

 

class Bmw implements Car  {    

    color : "red";

    wheels : 4;

    start(){

         console.log('go...');

    }

} 

 

◈ 생성자 이용

interface  Car   {

    color : string ;

    wheels : number ;

    start() : void ;

}

 

class Bmw implements Car  {    

    color: string;

    wheels: number = 4; // 기본값 설정

   

    consructor(c:string){

         this.color = c;

     }

 

    start(){

         console.log('go...');

    }

} 

 

const  b = new Bmw('green');

console.log(b);

b.start();

 

결과

 

◈ extends : 클래스 속성 확장가능

interface  Car   {

    color : string ;

    wheels : number ;

    start() : void ;

}



interface  Benz  extends Car {

    door : number ;

    stop() : void ;

}



const  benz : Benz = {

    door : 5 ,

    stop(){

        console.log('stop');

    } ,

    color : "green",

    wheels : 5 ,

    start(){

         console.log('go...');

    }                                            

}

 

 

◈ extends : 여러개 확장

interface  Car   {

    color : string ;

    wheels : number ;

    start() : void ;

}

 

interface  Toy{
    name: string ;
}

 

interface ToyCar extends Car , Toy{

    price : number

}

 


 


this

 

interface User{
    name : string;
}

const Sam : User = {name : 'Sam'}

function showName(this:User){        → this 타입 설정
    console.log(this.name)
}

const a = showName.bind(Sam);
a();

 

// 매개변수와 같이 쓸 경우

interface User{
    name : string;
}

const Sam : User = {name : 'Sam'}

function showName(this:User , age:number, gender : 'm'|'f'){
    console.log(this.name , age, gender)
}

const a = showName.bind(Sam);
a(30,'m');    넘기는 값은 2개만 넘기면 

 

※ bind

 

  • bind를 사용해 showName 함수의 this 값을 Sam 객체로 고정합니다.
  • 반환된 함수는 항상 this가 Sam을 참조합니다.

 

※ 참고 call, apply , bind 비교

공통점 : 

 

  • 세 메서드 모두 this를 명시적으로 지정할 수 있다.
  • bind, call, **apply**는 Function.prototype에서 제공되는 메서드다.
  • 함수의 실행 컨텍스트(this)를 조작하는 데 유용하다.
메서드 this 지정 인수전달방식 즉시 실행여부 반환값
bind 가능 개별적으로 지정 가능 아니요 새로운 함수 반환
call 가능 개별적으로 지정 가능 함수 실행 결과 반환
apply 가능 배열로 전달 함수 실행 결과 반환

 


오버로드 

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

function join(name:string, age:number) : User;  //--> 인자가 숫자로 넘어가면 User로
function join(name:string, age:string) : string; // --> 인자가 문자로 넘어가면 string 으로 오버로드 된 join 함수 사용
* 위처럼 오버로딩 하지 않을 경우 에러 남 인자를 숫자인지 문자인지에 따라 반환 데이터 타입이 달라지기 때문에.

function join(name : string, age : number | string) : User | string {
    if(typeof age === "number"){
        return {
            name,
            age,
        };
    }else{
        return "나이는 숫자로 입력해주세요";
    }  
}

const sam : User = join("Sam", 30);
const jane : string = join("Jane", "30");
 
 

 


제네릭(Generic)

* 함수에서 사용할때

//아래 처럼 여러타입이 모두 같은 함수를 쓰고 싶을때 함수정의해 주는 쪽에서 <T> 를 사용하고, 안의 글자는 뭐가됬던 상관없음

//호출하는 쪽에서 타입을 정해준다. 정해주지 않아도 타입을 추론하기 때문에 오류가 나지는 않는다.


function getSize<T>(arr:T[]):number{
    return arr.length;
}

const arr1= [1,2,3];
getSize<number>(arr1);

const arr2= ["a","b","c"];
getSize(arr2);

const arr3= [false, true, true];
getSize(arr3);

const arr4= [{},{},{name:"Tim"}];
getSize(arr4);

 

* 인터페이스에서 사용할때

interface Mobile<T>{
    name: string;
    price:number;
    option:T;
}

const m1:Mobile<object>={        → 명시적으로 작성해도 됨. <{color:string; coupon:boolean}>
    name: "s21",
    price:1000,
    option:{
        color:"red",
        coupon:false,
    },
}

const m2:Mobile<string>={
    name: "s20",
    price:1000,
    option:"good",
}

 


 

 

 

◈ 함수

class Car{          
    color: string;                                → ⓛ 선언해주지 않으면
    constructor(color : string){
        this.color = color;                    → ② color 에러 남
    }
    start(){
        console.log("start");
    }
}

const bmw = new Car("red");

 

 

선언하지 않고 사용할 수 있는 방법으로 접근제한자 이용 할수도 있음

 

1. public (기본 값)

  • 클래스 내부, 외부 어디서든 접근 가능.
  • 명시적으로 쓰지 않아도 기본 값으로 적용.
class Person {
    public name: string; // public 속성
    constructor(name: string) {
        this.name = name;
    }
    public greet() { // public 메서드
        console.log(`Hello, my name is ${this.name}`);
    }
}

const person = new Person("Alice");
console.log(person.name); // 출력: Alice (외부에서 접근 가능)
person.greet();           // 출력: Hello, my name is Alice
 
 

2. private ( # 기호를 써도 됨)

  • 클래스 내부에서만 접근 가능하며, 클래스 외부에서는 접근할 수 없다.
  • 인스턴스를 통해서도 접근할 수 없다.
  • 주로 클래스 내부에서만 사용해야 하는 데이터를 보호하기 위해 사용함.
class BankAccount {
    private balance: number; // private 속성
    constructor(initialBalance: number) {
        this.balance = initialBalance;
    }
    public deposit(amount: number) {
        this.balance += amount;
    }
    public getBalance() {
        return this.balance; // private 속성을 클래스 내부에서 사용
    }
}

const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 출력: 1500
console.log(account.balance);   // 에러: 'balance'는 private 속성이므로 접근 불가

3. protected

  • 클래스 내부상속받은 자식 클래스 내부에서만 접근할 수 있다.
  • 클래스 외부에서는 접근할 수 없다.( 인스턴스를 통해 접근할 수 없다 )
  • 주로 부모 클래스에서 정의한 속성을 자식 클래스에서 재사용하거나 확장할 때 사용함.
class Person {
    protected name: string; // protected 속성
    constructor(name: string) {
        this.name = name;
    }
    protected introduce() {
        console.log(`Hi, I am ${this.name}`);
    }
}

class Employee extends Person {
    private jobTitle: string;
    constructor(name: string, jobTitle: string) {
        super(name); // 부모 클래스의 생성자 호출
        this.jobTitle = jobTitle;
    }
    public describe() {
        this.introduce(); // protected 메서드에 접근 가능
        console.log(`I work as a ${this.jobTitle}`);
    }
}

const emp = new Employee("Bob", "Developer");
emp.describe();
// Hi, I am Bob
// I work as a Developer
console.log(emp.name); // 에러: 'name'은 protected 속성이므로 외부에서 접근 불가

 

static

  1. 클래스 자체에 속함:
    • static으로 선언된 속성이나 메서드는 클래스의 인스턴스가 아닌 클래스 자체에서 호출됨.
    • 인스턴스를 통해 접근할 수 없다.
  2. 공유 멤버:
    • 정적 멤버는 클래스의 모든 인스턴스가 공유함.
    • 객체마다 개별적으로 복사되지 않는다.
  3. 접근 제한자와 함께 사용 가능:
    • static 키워드는 public, private, protected 접근 제한자와 함께 사용할 수 있다.

 

class Car{
    readonly name: string = "car";
    color :string;
    static wheels = 4;

    constructor(color:string,name:string){
        this.color = color;
        this.name = name;
    }
    start(){
        console.log("start");
        console.log(this.name);
        console.log(Car.wheels);      → this 를 사용하면 에러남.클래스명으로 호출 해야함.
    }
}

class Bmw extends Car{
    constructor(color:string,name:string){
        super(color,name);
    }
    showName(){
        console.log(super.name);   
    }
}

const z4 = new Bmw("black","zzzz4");
console.log(Car.wheels);               → this 를 사용하면 에러남.클래스명으로 호출 해야함.
 
 
추상클래스

 

상속을 통해서만 사용 가능

구체적인 기능은 상속을 받은 쪽에서 구현

 

 


 


◈유틸리티

 

keyof :  객체 타입의 키(key)들을 문자열 리터럴 유니언 타입으로 추출하는 데 사용

interface User{
    id: number;
    name: string;
    age: number;
    gender: "m" | "f";
}

type UserKey = keyof User;  //=== 'id'| 'name' | 'age' | 'gender' 와 같음
 
const uk:UserKey = "age";

console.log(uk);

 

Partial<T> 프로퍼티를 모두 옵셔널로 바꿔줌

 

interface User{
    id: number;
    name: string;
    age: number;
    gender: "m" | "f";
}

let admin:Partial<User>={
    id:1,
    name:"Bob",
}
 
 
Required<T> 모든 프로퍼티를 필수로 바꿔줌
 
interface User{
    id: number;
    name: string;
    age?: number;
    gender: "m" | "f";
}

let admin:Required<User>={
    id:1,
    name:"Bob",
    age:30,                    → 모두 안쓰면 에러남
    gender: "m",
}

 

//Readonly<T> : 읽기전용, 최초할당 가능, 이후 수정 불가

 

//Record<K,T> : 키와 타입, 

interface User{
    id: number;
    name: string;
    age: number;
}

function isValid(user:User){
    const result:Record<keyof User, boolean> = {
        id:user.id > 0,
        name: user.name !== "",
        age: user.age > 0
    };
    return result;
}



// 예제 User 객체
const user1: User = { id: 1, name: "Alice", age: 25 };
const user2: User = { id: 0, name: "", age: -5 };

// 함수 호출 및 결과 확인
console.log(isValid(user1)); // 출력: { id: true, name: true, age: true }
console.log(isValid(user2)); // 출력: { id: false, name: false, age: false }

 

//Pick<T, K> :  T타입에서 K프로퍼티만 골라서 사용함.

interface User{
    id: number;
    name: string;
    age: number;
    gender:"M"|"W";
}

const admin:Pick<User,"id"|"name">={
    id:0,
    name: "Bob",
}
 
 
 

//Omit<> : T 타입에서 제외할 프로퍼티를 지정하여사용

interface User{
    id: number;
    name: string;
    age: number;
    gender:"M"|"W";
}

const admin:Omit<User,"age"|"gender">={
    id:0,
    name: "Bob",
}
 

 

//Exclude<T1, T2> : 타입1 중에서 타입2과 겹치는 타입을 제외

type T1 = string | number;
type T2 = Exclude<T1,number>;  // --> string 만 남음
 
 

//NonNullable<Type> : Null과 Undefined 를 제외

type T1 = string | number | void | null | undefined;
type T2 = NonNullable<T1>;  // --> string,number,void 만 남음

 

 


용어 : 
 리터럴

 

값을 직접 표현하는 방식,값 그 자체를 코드에 직접 작성한 것.

변수나 함수 호출의 결과가 아니라, 특정한 값을 명시적으로 코드에 적어 넣는 것을 리터럴이라고 함.

 

ex) 

const age = 25;  → 숫자형 리터럴

**={}**는 객체 리터럴을 사용해 객체를 초기화하는 문법.

ex) const Sam : User = {name : 'Sam'}


* implicitly : 암묵적으로

* A is assignable to B :  A를 B에 할당할 수 있다

댓글