youngst
Young St_____
youngst
  • 분류 전체보기 (30)
    • Dev (28)
      • JS Family, HTML, CSS (14)
      • Git & Github (0)
      • Projects (7)
      • else (5)
      • TIL (2)
    • 일상 (2)
      • 그냥 글 (1)
      • 사과 농장에서 살아남기 (1)

인기 글

태그

  • Next.js
  • ReactRouter
  • 후기
  • 옥소폴리틱스
  • 프론트엔드스쿨
  • React
  • 공부내용정리
  • GitHub-Page
  • 제로베이스
  • JavaScript
  • TypeScript
  • jsdoc
  • styled-components
  • Vite
  • 제로베이스스쿨
  • Firebase
  • react-router
  • CloneCoding
  • vscode
  • JSEvent

티스토리

hELLO · Designed By 정상우.
youngst

Young St_____

Dev/JS Family, HTML, CSS

[TypeScript] 타입스크립트 입문 (2) - 기본 타입, 클래스

2022. 9. 9. 22:20

타입 기본

기본 타입 훑어보기

원시 타입

  • 불변하는 타입
  • 객체가 아닌 값들
  • 원시 타입은 타입스크립트가 자동으로 타입 추론을 하기 때문에 생략해도 무방하다!
const str: string = 'STRING'
const num: number = 123
const bool: boolean = true

 

객체 타입

  • 객체 전체의 타입을 지정 가능
  • 객체 자체의 타입을 지정하면 any와 다를게 없다
/**
 * Object Type
 */

// object는 any와 다른게 없는 상황
const obj: object = {
  str: "str",
  num: 123,
  child: {
    str: "str",
    num: 123,
  },
};

// obj.num - object literal

const obj2: {
  str: string;
  num: number;
  child: {
    str: string;
    num: number;
  };
} = {
  str: "str",
  num: 123,
  child: {
    str: "str",
    num: 123,
  },
};

 

함수 타입

  • 매개 변수의 타입(Parameter)
  • 반환값의 타입(Return)
  • Return 값은 타입 추론이 가능하기 때문에 반드시 달아줄 필요는 없다
/**
 * Function Type
 */
function func(num: number, str: string): string {
    return num + str
}

func(123, 'str')

function func2(num1: number, num2: string): number {
    return num1 + Number(num2) //자동 형변환 방지
}

func2(123, '123')

function func3(num1: number, num2: string): void {
    console.log(num1 + num2)
}

func3(123, '123')

//! 반환형은 타입 추론이 가능하기 때문에 무조건 달아줄 필요는 없다!
const func4 = (str1: string, str2: string): string => {
    return str1 + ' ' + str2
}

func4('hello', 'world')

const func5 = (obj: { str1: string, str2: string }) => {
    return obj.str1 + ' ' + obj.str2
}


func5({ str1: 'hello', str2: 'world' })

 

배열 타입

  • 배열 전체의 타입을 지정 가능
  • 튜플이라는 별도의 형식도 존재!
/**
 * Array Type
 */
const strArr: string[] = ['str', 'str2', 'str3']

const strArr2: Array<string> = ['str', 'str2', 'str3']

const numArr: Array<number> = [1, 2, 3]

const boolArr: boolean[] = [false, true, false, true]

strArr.push(1) //error!
numArr.push('str') //error!
boolArr.push(false)

// Tuple
const arr = ['str', 123, false]

 

튜플 타입

  • 배열에서 길이와 index의 타입이 고정
  • 여러 다른 타입으로 이루어진 배열을 안전하게 관리 가능
  • 배열 타입의 길이를 조절 가능
/**
 * Tuple Type
 */
const arr: string[] = ['A', 'B', 'C']

// 길이 고정
const tuple: [number, string] = [1, 'A']

// Union Type
const tuple0: (string | number)[] = [1, 'A']

const tuple2: [number, ...string[]] = [0, 'A', 'B']

 

undefined & null

  • undefined으로 뭉뚱그려 처리하는 것 대신 void, never 등 더 세밀한 타입을 제공
  • vanila JS와 마찬가지로 각각을 고유한 타입으로 인정한다.
  • strictNullChecks가 핵심
    • strictNullChecks: 개발자가 null이나 undefined 값을 참조하지 않도록 에러를 보여준다.
    • 실제로 참고하지 않더라도 참고할 가능성이 있을 때도 컴파일 에러를 보여줘서 안전한 코딩이 가능하다
/**
 * undefined & null
 */

//되도록 둘 중 하나만 사용하기!
const nu: null = null;
const un: undefined = undefined;

function sayHello(word: string) {
    if (word === 'world') {
        return 'hello' + word
    }

    return null
}

function log(message: string | number) {
    console.log(message)
}

 

any

  • 모든 값(타입)의 집합
  • 사용하지 말자!!!(타입스크립트의 의미가 없어진다)
  • noImplicitAny or strict 옵션 true 권장 - 자동으로 any 형 변환 되는 것을 막아준다
/**
 * any
 */
function func(anyParam: any) {
    anyParam.trim()
}

func([1,2,3])

 

unknown

  • any 대신 새로 추가된 최상위 타입
  • any처럼 모든 값을 허용하지만 상대적으로 엄격하다.
  • 타입 추론 대상에서 제외되므로 개발자가 직접 명시해야 한다.
  • assertion 혹은 Type guard와 함께 사용한다.
/**
 * unknown
 * 
 * 새로운 최상위 타입
 * any처럼 모든 값을 허용하지만 상대적으로 엄격하다.
 * TS에서 unknown으로 추론하는 경우는 없으니 개발자가 직접 명시해야함
 * assertion 혹은 타입 가드와 함께 사용한다.
 */
let num: unknown = 99;

//타입 가드
if (typeof num === 'string') {
    num.trim();
}

// (num as string).trim();

//// 모두 에러 발생 안함!
// function func(x: any) {
//     let val1: any = x; 
//     let val2: unknown = x;
//     let val3: string = x;
//     let val4: boolean = x;
//     let val5: number = x;
//     let val6: string[] = x;
//     let val7: {} = x;
// }

// // any와 unknown만 가능
// function func(x: unknown) {
//     let val1: any = x; 
//     let val2: unknown = x;
//     let val3: string = x; //err
//     let val4: boolean = x; //err
//     let val5: number = x; //err
//     let val6: string[] = x; //err
//     let val7: {} = x; //err
// }

 

void

  • 함수의 반환이 없는 경우를 명시
  • return이 없으면 자동으로 타입추론하므로 타입추론에 위임하자!
  • 바닐라 JS에서는 undefined를 반환하지만 TS에서 void와 undefined는 같은 것이 아니다.
/**
 * void
 */

//명시하지 않아도 void 반환 함수
function test() {
	console.log("void fucntion");	
}

 

 

클래스

  • JavaScript에서는 ES2015의 새로운 문법으로 도입
  • 객체 지향형 프로그래밍의 핵심
  • TypeScript에서의 클래스 기능은 C#(MS사 개발)에서 유래된 것이 많다.
  • 일부 기능(인터페이스 등)은 TS에서만 존재하는 고유 문법이기때문에 JS로 컴파일 후에는 사라진다.

생성자 & 인스턴스

/**
 * Class
 */
class Person {
  /**
   * 필드
   * - 일종의 속성
   * - public으로 사용가능합니다.
   */
  name: string;
  age: number;
  readonly location: string = "Korea";

  /**
   * 생성자
   * 
   * - 초기화를 담당
   */
  constructor(name: string, age: number) {
      this.name = name
      this.age = age
  }
}

/**
 * 인스턴스
 *
 * - 클래스에서 파생된 고유한 것
 * - 실제로 생성된 후 메모리에 올라감
 */
const p1 = new Person('Jang', 99);
const p2 = new Person('Poco', 100);

console.log(p1)
console.log(p2)

 

메서드

  • 객체(클래스)에 포함된 함수
/**
 * method
 */
class Person {

  name: string;
  age: number;
  readonly location: string = "Korea";

  constructor(name: string, age: number) {
      this.name = name
      this.age = age
  }

  /**
   * 메서드
   * 
   * 객체(클래스)에서는 행동을 뜻한다.
   */
  introduce(): string {
    return `${this.name}의 나이는 ${this.age} 입니다.`
  }
}

const p1 = new Person('Jang', 99);
const p2 = new Person('Poco', 100);

console.log(p1.introduce())
console.log(p2.introduce())

 

Getter & Setter

  • 필드에 접근할 권한을 가진 제어자
  • getter만 있고 setter가 없다면 속성은 자동으로 readonly가 된다.
  • setter 매개변수의 타입이 없어도 getter의 반환 타입에서 추론한다.
  • private 속성은 자식(.) 연산자로 접근할 수 없다.
/**
 * Getter & Setter
 */
class Person {
  name: string;
  //프라이빗 변수는 보통 _를 붙인다
  private _age: number;

  constructor(name: string, age: number) {
      this.name = name
      this._age = age
  }

  get age() {
    if (this._age === 0) {
      return '설정되지 않았습니다.'
    }

    return `나이는 ${this._age}세로 추정됩니다.`
  }

  set age(age) {
    // 타입 가드
    if (typeof age === 'number') {
      this._age = age
    }

    this._age = 0;
  }
}

const p = new Person('Jang', 0)
console.log(p.age)
console.log(p.name)

 

extends

  • 클래스를 상속 받을 수 있다
  • 확장의 개념
/**
 * extends
 */
class 기본 {
  result() {
    return 'Base'
  }
}

class 파생 extends 기본 {
  //overriding
  result() {
    return 'Derived'
  }
}

const de = new 파생()

console.log(de.result())

 

super

  • 상속 받는 클래스에서 부모 클래스의 요소 호출 시 사용
  • 생성자에서 this 사용 전에 호출되어야 한다.
/**
 * super
 */
class Animal {
  name: string

  constructor(name: string) {
    this.name = name
  }

  sayName() {
    return `동물의 이름은 ${this.name}`
  }
}

class Person extends Animal {
  constructor(name: string) {
    super(name)
  }

  sayName() {
    return `${super.sayName()} 사람의 이름은 ${this.name}`
  }
}

class Jang extends Person {
  
}

const person = new Person('Jang')

console.log(person.sayName())

 

접근제어자

  • 속성과 메서드에 접근을 제한할 수 있다
  • 클래스 내부 구현 정보를 적당히 공개하여 일부분만 노출시킨다.
  • API와 비슷한 흉내를 낼 수 있다
  • 타입 시스템을 이용해 규칙을 강제할 수 있다
public 어디서나 접근 가능(기본값)
protected 해당 클래스와 서브클래스에서만 접근 가능
private 해당 클래스에서만 접근 가능
/**
 * 접근제어자
 */
class Person {
  public name: string
  private age: number
  protected gender: 'M' | 'F'

  constructor(name: string, age: number, gender: 'M' | 'F') {
    this.name = name
    this.age = age
    this.gender = gender
  }

  sayName() {
    return `이름은 ${this.name} 입니다`
  }

  protected sayAge() {
    return `나이는 ${this.age}`
  }

  private sayGender() {
    return `성별 타입은 ${this.gender}`
  }
}

class Me extends Person {
  constructor(name: string, age: number, gender: 'M' | 'F') {
    super(name, age, gender)
  }

  sayInfo() {
    //sayGender 에러 발생
    return `${super.sayGender()} ${super.sayAge()} ${super.sayName()}`
  }
}

const p = new Person('jang', 99, 'M')

 

static

  • 클래스의 속성과 메서드를 new로 인스턴스화 하지 않고 호출할 수 있다
  • 접근 제어자를 활용할 수 있다
  • 몇 가지 정적 이름을 사용할 수 없다
    • 클래스는 그 자체로 new로 호출할 수 있는 함수이기 때문
    • 예) function.name (불가능)
/**
 * static
 */
class StaticClass {
  private static type = 'Type'
  static name = 'name' //name은 function의 빌트인 속성이라 사용 불가!


  static getType() {
    return StaticClass.type
  }
}

// console.log(StaticClass.type)
console.log(StaticClass.getType())

 

readonly

  • TS에만 존재
  • 말 그대로 수정은 안 되고 읽기만 가능하다
/**
 * readonly - TS에만 존재
 */
class Person {
  name: string
  readonly age: number

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //error 발생!
  setAge(newAge: number) {
    this.age = newAge
  }
}

const p = new Person('Jang', 99)

p.name = 'JJJ' //아무나 수정 가능!
p.age = 30 //error!

 

추상 클래스

  • abstract를 선언한 클래스로, 직접 인스턴스화(new) 될 수 없는 클래스이다
  • 일종의 클래스 설계도
  • 직접 인스턴스화 될 수는 없지만 extends 후 파생된 클래스를 인스턴스화 하도록 유도한다.
  • 추상 클래스는 구현된 메서드를 포함시킬 수 있다
  • abstract를 선언한 메서드는 파생된 클래스에서 메서드를 반드시 구현해야한다.
/**
 * 추상 클래스
 */
abstract class Animal {
  // 선언된 메서드 - 반드시 구현!
  abstract hello(): string
 
  // 구현된 메서드
  run() {
    return this.hello() + ' run'
  }
}
 
// 직접 인스턴스가 될 수 없다.
// const animal = new Animal()

class Person extends Animal {
  hello() {
    return 'Person'
  }
}

class Dog extends Animal {
  hello() {
    return 'Dog'
  }
}

const person = new Person()
const dog = new Dog()

console.log(person.hello())
console.log(dog.hello())

 

Pararmeter Properties

  • 클래스 생성과 동시에 생성자 선언
  • this.~ 를 이용한 타입 초기화를 생략할 수 있다
/**
 * Parameter Properties
 */
class Person {
  //타입 정하면서 동시에 생성자 선언 + this.~ 생략가능!
  constructor(
    public name: string,
    private age: number,
    protected gender: 'M' | 'F'
    ) { //this.name = name 생략 가능
  }

	...
}

 

Method Overriding

상속 받은 메서드 덮어 쓰기

/**
 * 메서드 오버라이딩
 */
class Animal {
  run() {
    return 'Animal이 달리다'
  }
}

class Dog extends Animal {
  run() {
    return 'Dog가 달리다'
  } 
}
 
class Person extends Animal {
  run() {
    return 'Person이 달리다'
  } 
}

const a = new Animal()
const p = new Person()
const d = new Dog()

console.log(a.run())
console.log(p.run())
console.log(d.run())

 

 

그래도 이전에 JAVA와 C++을 한 덕분인지 이해하기 쉬웠다! JavaScript를 열심히 공부한 보람이 있다ㅎㅎㅎ

저작자표시 비영리 변경금지

'Dev > JS Family, HTML, CSS' 카테고리의 다른 글

[TypeScript] 타입스크립트 입문 (4) - 제네릭, 고급 타입 다루기  (0) 2022.09.14
[TypeScript] 타입스크립트 입문(3) - 인터페이스, 타입 가드, 열거형, 유니온 타입  (0) 2022.09.12
[TypeScript] 타입스크립트 입문(1)  (2) 2022.09.04
[React] 일주일만에 리액트 정복하기! (2)  (0) 2022.08.03
[React] 일주일만에 리액트 정복하기! (1)  (1) 2022.08.02
    'Dev/JS Family, HTML, CSS' 카테고리의 다른 글
    • [TypeScript] 타입스크립트 입문 (4) - 제네릭, 고급 타입 다루기
    • [TypeScript] 타입스크립트 입문(3) - 인터페이스, 타입 가드, 열거형, 유니온 타입
    • [TypeScript] 타입스크립트 입문(1)
    • [React] 일주일만에 리액트 정복하기! (2)
    youngst
    youngst
    좋은 프론트엔드 개발자가 되고 싶습니다

    티스토리툴바