Front-end/TypeScript Language

TypeScript 언어 정리

prden 2024. 4. 14. 14:23

1. Java, TypeScript(정적 언어) 

컴파일 시점에 타입 결정하고 그때 오류 발견한다.

(JavaScript : 런타임 시점에 타입 오류 확인 가능)

타입 설정하지 않으면 타입스크립트는 any로 설정함.

function add(num1:number, num2:number){
    console.log(num1 + num2);
}

add(1,2); // 3
add(); // NaN = undefined + undefined

function showItems(arr:string[]){
    arr.forEach((item) => {
        console.log(item);
    });
}
showItems(['1','2','3']) // 1 2 3

 

2. 타입 지정 

let age:number = 30;
let isAdult:boolean = true;
let a:number[] = [1,2,3];
위랑 동일, let a2:Array<number> = [1,2,3];
let myName:{name : string} = {name : 'kim'};
let myName:string | number = 'kim';

type Member = {
	[key :string] : string, // 글자로 된 모든 object 속성의 타입은 : string이다.
 }
let john : Member = {name : 'kim'}

//튜플(인덱스 별로 타입 다를 때)
let b:[string, number];
b = ['z', 1];
b[0].toLowerCase();

//void, never
function 함수(x:number) : number { // return 타입 인자 뒤에 : 로 지정
	return x*2
}
function sayHello():void{
    console.log('hello')
}

never : 에러 던지거나 무한 루프 돌 때 리턴 타입에 선언

//에러 던질 때 보통 never
function showError():never{
    throw new Error();
}

//무한 루프 돌 때 never
function infLoop():never{
    while(true){
        // do something
    }
}

//enum(이넘)
enum Os{
    Window, //0
    ios, //1
    android //2
}

Window = 3이라고 하면 ios는 4가되고, android는 5가된다.

let myOs:Os;
라고하면 myOs는 Os에 있는 것만 사용할 수 있다.
myOs = Os.Window 이런 식으로 

// 이넘 활용 예제
enum Answer {
 Yes = 'Y'
 No = 'N',
 }
function askQuestion(answer : Answer) {
 if(answer ===Answer.Yes) {
  console.log('정답입니다.');
 }
 if(answer ===Answer.No) {
  console.log('오답입니다.');
 }
 
askQuestion('예스'); // 오류
askQuestion('y'); // 오류
askQuestion('Yes'); // 오류

askQuestion(Answer.Yes);

}

//null, undefined

let a:null = null;
let b:undefined = undefined;

type vs inteface // 타입과 인터페이스의 차이
1. 타입별칭과 인터페이스의 가장 큰 차이는 확장 가능여부이다. 
- 인터페이스는 확장 가능, 타입은 불가능.

 

3. 객체

// interface

interface User{
    name: string;
    age: number;
}
let user : User = {
    name : 'hahaha',
    age: 30
}
console.log(user.age);

//입력해도 되고 안해도 되면 -> ?(Optional) 

interface User{
    name: string;
    age: number;
    gender?:string;
}
let user : User = {
    name : 'sungjun',
    age: 30,
}

user.age =10;
user.gender = "male";

console.log(user.age);


Union Type // 하나 이상의 타입 쓸 수 있게 
interface Developer {
 name : string;
 skill : string;
}

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

function askSomeone(someone: Developer | Person) {
 somone.name ; // 공통된 속성만 사용가능하다.
 someone.skill // 불가
 someone.age // 불가
}

// InterSection Type

function askSomeone(someone: Developer & Person) {
 somone.name ; // 가능
 someone.skill // 가능
 someone.age // 가능
}

// 읽기 전용이면 변수 앞에 readonly 
type Score = 'A' | 'B' | 'C' | 'F';

interface User{
	name: string;
    age: number;
    gender? : string;
    readonly birthYear : number;
    [grade:number] : Score;
    //key를 number로 하고 value를 string으로 하는 것 여러 개 적을 수 있다.
    }
    
interface Add {
	//인자 넣고 맨뒤 반환 값 : number
	(num1: number, num2: number): number;
    }

const add : Add = function(x,y){
	return x + y;
	}

add(10,20);

interface IsAdult {
	(age:number): boolean;
    }
    
//화살표로 함수 표시하기 
const a : IsAdult = (age) => {
	return age > 19;
    }
a(30) //true
 
 //implements
 interface Car{
 	color:string;
    wheels:number;
    start():void;
   }
 interface Toy{
 	name:string;
   }   

class Bmw implements Car{
	color;
    wheels = 4;
    constructor(c:string){
    	this.color = c;
       }
    start(){
    console.log('go..');
    }
 }
 
 const b = new Bmw('green');
 console.log(b)
 b.start(); //go..
 
 //extends
 
 interface Benz extends Car {
 	door : number;
    stop(): void;
    }

const benz : Benz = {
	door : 5, 
    stop(){
    	console.log('stop');
        }
    color : 'red',
    wheels: 4,
    start() {
    	console.log("START");
    }
}

interface ToyCar extends Car, Toy {
	price : number;
}

//딕셔너리 패턴
interface StringRegexDictionary { 
	[key: string]: RegExp;
}

const obj : StringRegexDictionary = {
	cssFile: /\.css$/,
    jsFile: /\.js$/,
}
obj['cssFile'] = 'a' // 에러

 

4. 함수 타입

// return type을 인자 뒤에 : 로 표시해주면 된다. 

function isAdult(age:number): boolean {
    return age > 19;
}

//name은 있어도 되고 없어도 된다. 없으면 world가 나옴.

function hello(name?: string){
    return `Hello, ${name || "world"}`;
}

function hello2(name = "world"){
    return `Hello, ${name}`;
}
const result = hello();

// 이렇게 선택적 매개변수가 필수 매개변수보다 앞에오면 오류 발생한다. 
// 선택적 매개변수는 뒤로 빼야함.
function hello(age?:number, name:string):string {
  if (age != undefined) {
   return `Hello, ${name}. You are ${age}.`;
  } else {
   return `Hello, ${name}`;
  }
}

//...nums 여러 매개변수, 배열 형태로 나열할 수 있다.
function add(...nums: number[]){
    return nums.reduce((result, num) => result + num, 0);
}

add(1,2,3); // 6
add(1,2,3,4,5,6,7,8,9,10); // 55

interface User {
    name:string;
}

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

//this를 사용하는 경우 
//매개 변수에 this이렇게 넣어 줘야 한다. 
function showName(this:User){
    console.log(this.name)
}

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

//오버로드 사용
interface User{
    name:string;
    age:number;
}

//1st
function join(name:string, age:number):User;
//2nd
function join(name:string, age:string):string;

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

//1st 예시
const sam:User = join("Sam", 30);
//2nd 예시
const jame:string = join("Jane", "30");

 

5.Literal Types

//const 변하지 않는 값 선언
//let 변하는 값 선언

//문자열 literal type, Bob이 string으로 변하지 않는값 명시적으로 선언해 놓은 것
const userName1 = "Bob";

//username2는 string type
let userName2 = "Tom";

type Job = "police" | "developer" | "teacher";

interface User {
    name: string;
    job :Job;
}

const user: User = {
    name: "Bob",
    job:"developer"
}
console.log(user);


//유니온 타입 =  A 또는 B = |
interface Car{
    name: "car";
    color :string;
    start(): void;
}

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

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

//intersaction type ( and 의미)

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

interface Mobile {
    name: string;
    color : string;
    price:number;
}
//교차타입의 여러개의 객체를 하나로 합쳐주는 것, 모든 속성을 다 기입해줘야한다. 
const toyCar: Toy & Car = {
     name: "타요",
     start(){},
     color : "빨강",
     price:1000
}

 

6. 클래스

//접근 제한자(Access modifier) - 
//public -  자식 클래스, 클래스 인스턴스 모두 접근 가능
//private(=#) - 해당 클래스 내부에서만 접근 가능
//protected(자식 클래스 내부에서 사용가능, 클래스 인스턴스에서는 참조 불가능)


class Car {
	private color : string; // 자식클래서 내부에서 사용 못한다.
    static wheels = 4;
	constructor(color:string){
    this.color = color;
    }
    start(){
     console.log("start");
     console.log(Car.wheels); // 정적 맴버변수는 this가 아니라 클래스를 적어준다. 
    }
}

const bmw = new Car("red");

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

// 추상 class

abstract class Car {
	private color : string; // 자식클래서 내부에서 사용 못한다.
    static wheels = 4;
	constructor(color:string){
    this.color = color;
    }
    start(){
     console.log("start");
     console.log(Car.wheels); // 정적 맴버변수는 this가 아니라 클래스를 적어준다. 
    }
}

// 추상클래스는 인스턴스 생성 못함, 상속을 통해서만 이용 가능
const car = new Car("red");

class Bmw extends Car {
 constructor(color:string){
  super(color);
  }
}

 

7. 제네릭

// Generic
function getStie(arr: number[] | string[] | boolean[] | object[]):number {
	return arr.length;
}

const arr1 = [1,2,3];
getSize(arr1); // 3
const arr2 = ["a","b","c"];
getSize(arr2); // 3
const arr3 = [false, true, true];
getSize(arr3); // 3
const arr4 =[{}, {}, {name:"Tim"}];
getSize(arr4); // 3

//이렇게 하는 것 보다 제네릭 사용

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

const arr1 = [1,2,3];
// 사용하는 쪽에서 타입 지정
getSize<number>(arr1); // 3
const arr2 = ["a","b","c"];
getSize<string>(arr2); // 3
const arr3 = [false, true, true];
getSize<boolean>(arr3); // 3
const arr4 =[{}, {}, {name:"Tim"}];
getSize<Object>(arr4); // 3

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

const m1: Mobile<{color : string; coupon: boolean }> = {
 name : "s20";
 price : 900;
 option : {
   color : "red",
   coupon: false,
   },
};

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

// 제네릭의 타입 제한
function logTextLength<T>(text: T[]):T[] {
 console.log(text.length);
 text.forEach(function (text) {
  console.log(text);
 });
 return text;
}

logTextLength<string>(['hi', 'abc']);

// 제네릭 타입 제한 2 - 정의된 타입 이용하기
interface LengthType {
 length : number;
}

function logTextLength<T extends LenthType>(text: T): T {
 text.length;
 return text;
}
logTextLength(10); // 오류

// 제네릭 타입 제한 3 - keyof로 줄이기 인터페이스의 키만 들어갈 수 있다.
interface ShoppingItem {
  name: string;
  price: number;
  stock: number;
 }

 function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T):T {
  return itemOption;
 }

 

8. 유틸리티 타입

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

type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'

const uk : UserKey = "";

// Partial<T> // 프로퍼티를 모두 optional로 바꿔줌
interface User {
 id?: number;
 name?: string; 
 age?: number;
 gender? : "M" | "F";
}

let admin:Partial<User> = {
 id: 1, 
 name: "Bob",
}

//Required<T> // 모든 프로퍼티가 필수 값
//Readonly<T> // 읽기만 가능, 수정 불가

//Record<K,T> // K : 키, T : 타입
type Grade = "1"| "2"| "3"| "4"| "5" ;
type Score = "A"| "B"| "C"| "D"| "E" ;
const score = Record<Grade, Score> = {
 	1: "A",
 	2: "B",
 	3: "C",
 	4: "D",
 	5: "E",
};

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

//Pick 객체에서 특정 프로퍼티만 꺼내서 사용
//Omit 특정 프로퍼티 생략해서 사용 가능
//Exclued<T1,T2> : T1타입 중에서 T2타입에 겹치는 것 제외 함

const admin : Pick<User, "id" | "name">= {
 id: 0,
 name : "Bob",
 };
 
 type T1 = string | number | boolean;
 type T2 = Exlcude<T1, number | string;
 
 //NonNullable<Type> // Null을 제외한 타입 제거( null, undefinded )
 
 type T1 = string | null | undefined | void;
 type T2 = NonNullable<T1>; // string, void만 남음

 

 

https://joshua1988.github.io/ts

 

타입스크립트 핸드북

 

joshua1988.github.io