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
- 클래스 자체에 속함:
- static으로 선언된 속성이나 메서드는 클래스의 인스턴스가 아닌 클래스 자체에서 호출됨.
- 인스턴스를 통해 접근할 수 없다.
- 공유 멤버:
- 정적 멤버는 클래스의 모든 인스턴스가 공유함.
- 객체마다 개별적으로 복사되지 않는다.
- 접근 제한자와 함께 사용 가능:
- 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에 할당할 수 있다
댓글