[07.26] Typescript

0
post-thumbnail

📌 Typescript 환경설정

Typescript 프로젝트 환경설정

npx create-react-app [폴더명] --template typescript

Typescript ESLint와 Prettier설정

  • ESLint : 코드의 잘못된 문법을 잡아주는 확장 프로그램
  • Prettier : 코드를 보기 좋게 정리해주는 확장 프로그램

📌 Typescript

자바스크리브는 동적 타입(코드 실행시 알아서 변수타임을 표현) 언어로서 자유도가 높아 진입 장벽이 낮고 생산성이 높은 대신, 형식이 정해져 않기 때문에 오류(버그)가 런타임 중에 발생한다거나, 또는 팀원간의 소통의 오류가 단점으로 생겨난다

  • 코드의 가독성과 유지 보수성을 높여줌
    -> 런타임 에러를 최소화하고, 코드 작성 시간을 단축하여 협업시 코드의 가족성을 높여줌
  • 타입을 명시함으로써 코드의 의도가 명확해지기 때문에 다른 개발자가 봐도 코드의 이해와 수정이 간편해지고 런타임 에러를 사전에 방지할 수 있어서 유지보수성 또한 높음

📌 Typescript의 타입

Boolean(불리언)타입

참(true)과 거짓(false)

let isDone: boolean = false;
let isShow: boolean = true;

console.log(isDone); // false
console.log(isShow); //true

Number(숫자)타입

정수와 실수의 구분 없이 사용

let num1: number = 7;
let num2: number = 0.6878;

console.log(num1); // 7
console.log(num2); // 0.6878

String(문자열)타입

큰 따옴표(""), 작은 따옴표('')사용하여 문자열 데이터를 표현

let str: string = 'hello';

console.log(str); //hello

Array(배열)타입

값들을 배열로 나열

/* 숫자형 배열의 타입을 정하는 2가지 방법 */
let list1: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];

console.log(list1); // [1, 2, 3];
console.log(list2); // [1, 2, 3];

/* 문자형 배열의 타입을 정하는 2가지 방법 */
let list3: string[] = ['banana', 'apple', 'mango'];
let list4: Array<string> = ['banana', 'apple', 'mango'];

console.log(list3); // ['banana', 'apple', 'mango'];
console.log(list4); // ['banana', 'apple', 'mango'];

Tuple(튜플)타입

요소의 타입과 개수가 고정된 배열을 표현

let list5: [number, string, boolean] = [1, 'banana', true];

console.log(list5); // [1, 'banana', true];

Object(객체)타입

객체의 프로퍼티 타입들을 각기 명시

let obj: object = {};
let obj2: { name: string; age: number; isDeveloper: boolean } = {
  name: 'kimcoding',
  age: 20,
  isDeveloper: true,
};

console.log(obj);
console.log(obj2);

Any 타입

타입 검사를 하지 않고자 할때 사용 (사용을 권장 x)


📌 Typescript 함수

Javascript

//named function
function add(x, y){
	return x + y;
}

//arrow function
let add = (x, y) => {
	return x + y;
}

Typescript

  • 반환되는 return 값은 타입추론을 이용하여 생략가능
  • 매개변수의 타입과 수에 맞게 전달인자를 전달해야함
//named function
function add(x: number, y: number):number {
	return x + y;
}

//arrow function
let add = (x: number, y: number): number => {
	return x + y;
}
  • 만약에 함수의 리턴값이 없다면 , void를 사용하여 작성
let printAnswer = (): void => {
	console.log("YES");
}
  • 선택적 매개변수를 원한다면 매개변수의 이름 끝에 물음표(?)를 붙임
    -> 하지만 맨 첫번째 매개변수에 선택적 매개변수는 오면 안됨

실습

/* 1-1번 */
function sumNumber(a: number, b: number): number {
  return a + b;
}

/* 1-2번 */
const sumNumber2 = (a: number, b: number): number => {
  return a + b;
};

/* 2번 */
let sumString = (first: string, last: string): string => {
  return `${first} ${last}`;
};

console.log(sumString('hi', 'codestates'));

/* 3번 */
let sumString2 = (first: string, last: string): string => {
  return `${first} ${last}`;
};

//아래 코드도 동작하도록 구현해봅시다.
console.log(sumString2('hi', 'codestates'));

/* 4번 */
let printError = () => {
  console.log('error message');
};

📌 Union타입과 Intersection 타입

Union 타입

모든 타입에 공통인 멤버들에만 접근이 가능 (|연산자 사용

  • 타입을 추론할 수 있기 때문에 타입에 관련된 API를 쉽게 자동완성으로 얻어낼 수 있음
    -> any 타입을 사용하면 타입 추론이 불가능하니 유의해서 사용
  • 타입을 지정해주면 명시적으로 표시된 코드로 인해 코드의 가독성을 높일 수 있음
function getGift(gift: Car | Mobile){
    // 조건문을 달지 않고 gift.name을 return하면 에러가 발생
    // car에만 start()가 있기 떄문 -> 그래서 조건문을 달아줌
    if(gift.name === "car") {
        gift.start();
    } else {
        gift.call();
    }
}
  • 공통되고 보장된 프로퍼티에만 접근할 수 있기 때문에 나머지 프로퍼티에 접근하고 싶다면 타입 가드를 사용해야함

    📍 타입가드란?
    Typescript에서 타입을 보호하기 위해 사용되는 기능 중 하나로서 특정 코드 븍록에서 타입의 범위를 제한해 해당 코드 블록 안에서 타입 안정성을 보장해줌

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

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

// askSomeone 함수내부에서는 Developer와 Person이 갖고 있는 
// 공통 프로퍼티인 name에만 접근할 수 있음
function askSomeone(someone: Developer | Person) {
	console.log(someone.name);
}

function askSomeone(someone: Developer | Person) {
  // in 연산자 : 타입스크립트에서 객체의 속성이 존재하는지를 체크하는 연산자
  // in 연산자는 객체의 속성 이름과 함께 사용하여 해당 속성이 객체 내에 존재하는지 여부를 검사
  if ('skill' in someone) {
    console.log(someone.skill);
  }

  if ('age' in someone) {
    console.log(someone.age);
  }
}

Intersection 타입

둘 이상의 타입을 결합하여 새로운 타입을 만드는 방벙 (&연산자 사용)

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

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

function askSomeone(someone: Developer & Person) {
  console.log(someone.age);
  console.log(someone.name);
  console.log(someone.skill);
}
// 인터섹션 타입으로 결합하게 된다면 전달인자를 전달할때 선택지가 없음
// 유니온타입은 타입가드를 사용하면 선택지가 생김
askSomeone({name:'김코딩', skill:'웹 개발', age:20});

📌 Typescript 인터페이스(Interface)

타입 체크를 위해 사용이 됨

  • 변수, 함수, 클래스에 사용할 수 있으며, 인터페이스에 선언된 프로퍼티 또는 메서드의 구현을 강제하여 일관성을 유지
interface User {
	name: string;
	age: number;
}

// 정상적으로 선언됩니다.
const user: User = {
	name: "anna",
	age: 20
}

// 프로퍼티의 순서를 지키지 않아도 정상적으로 선언됩니다.
const user: User = {
	age: 20,
	name: "anna"
}

// 정의된 프로퍼티보다 적게 작성했기 때문에 에러가 납니다.
const user: User = {
	name: "anna"
}

// 정의된 프로퍼티보다 많이 작성했기 때문에 에러가 납니다.
const user: User = {
	name: "anna",
	age: 20,
	job: "developer"
}

함수 인터페이스

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

interface Greeting {
	(user: User, greeting: string): string;
}

const greet: Greeting = (user, greeting) => {
	return `${greeting}, ${user.name}! Your job : ${user.job}.`;
}

const user: User = {
	name: "anna",
	age: 30,
	job: "developer"
};

const message = greet(user, "Hi");

console.log(message);

클래스와 인터페이스

interface Calculator {
	add(x: number, y: number): number;
	substract(x: number, y: number): number;
}

class SimpleCalculator implements Calculator {
	add(x: number, y:number) {
		return x + y;
	}

	substract(x: number, y: number) {
		return x - y;
	}
}

const caculator = new SimpleCalculator();

console.log(caculator.add(4, 9)); // 13
console.log(caculator.substract(10, 5)); // 5

실습

interface Todo {
  id: number;
  content: string;
  isDone: boolean;
}
// Todo 인터페이스를 타입으로 받는 todos를 완성합니다.
let todos: Todo[] = [];

// Todo 인터페이스를 타입으로 받는 addTodo를 완성합니다.
function addTodo(todo: Todo): void {
  todos = [...todos, todo];
}

// Todo 인터페이스를 타입으로 받는 newTodo를 완성합니다.
const newTodo = {
  id: 1,
  content: 'learn typescript',
  isDone: false,
};

addTodo(newTodo);

console.log(todos);

인터페이스와 상속

클래스 확장할때 extends라는 키워드를 사용해 기존에 존재하던 클래스를 상속해 새로운 클래스를 정의

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

interface Developer extends Person {
    language: string;
}

const person: Developer = {
    language: "TypeScript",
    age: 20,
    name: "Anna",
}

📌 Typescript의 타입 별칭

타입의 새로운 이름을 만드는 것

type MyString = string;

let str1: string = 'hello!';

// string 타입처럼 사용할 수 있습니다.
let str2: MyString = 'hello world!';
  • 타입 별칭을 사용하면 코드를 더 간결하고 가독성 좋음
  • 복잡한 타입을 간략하게 표현하고, 타입 정의를 재사용하는 등 가독성을 높일 수 있음
  • 타입은 확장을 사용할 수 없음
type Person = {
  id: number;
  name: string;
  email: string;
}

//Commentary 인터페이스에서 Person 타입을 참조하고 있습니다.
interface Commentary {
  id: number;
  content: string;
  user: Person;
}

//객체에서 Commentary 인터페이스를 참조하고 있습니다.
let comment1: Commentary = {
    id: 1,
    content: "뭐예요?",
    user: {
        id: 1,
        name: "김코딩",
        email: "kimcoding@codestates.com",
    },
}

//Commentary 인터페이스 내부에 content 프로퍼티가 존재하기 때문에 
//content 프로퍼티를 작성하지 않으면 컴파일 에러가 납니다.
let kimcoding: Commentary = {
    id: 1,
    user: {
        id: 1,
        name: "김코딩",
        email: "kimcoding@codestates.com",
    },
};

//Person 타입 내부에 isDeveloper 프로퍼티가 존재하지 않기 때문에 
//isDeveloper 프로퍼티를 작성할 시 컴파일 에러가 납니다.
let kimcoding: Commentary = {
    id: 1,
    content: "뭐예요?",
    user: {
        id: 1,
        name: "김코딩",
        email: "kimcoding@codestates.com",
        isDeveloper: true,
    },
};

📌 Typescript의 타입 추론

0개의 댓글