TypeScript 기본 타입

Goofi·2023년 2월 20일
0
post-custom-banner

TypeScript

타입스크립트는 strongly-typed 언어이다.

strongly-typed 이란, 프로그래밍 언어가 작동하기 전에 type을 확인한다는 것이다.

❗️자바스크립트는 strongly-type이 아니다.

1️⃣ 타입스크립트와 자바스크립트 특징

  • 타입스크립트는 동적타입이다.
    - 개발 시에 변수와 매개변수의 타입정의가 끝난다. 런타임에 변경되지 않는다.
  • 자바스크립트는 정적타입이다.
    - 런타임에서 변수의 타입이 변경된다.
  • 자바스크립트는 런타임이 완료 된 후 변수가 어떤 타입인지 확인하는 typeof연산자가 있다.

2️⃣ 타입스크립트 장점 및 자바스크립트 문제점

타입스크립트 장점

타입 안전성
1. 코드에 버그가 줄게된다.
2. 런타임 에러가 줄여진다.
→ 런타임에서 오류가 발생하기전에 막아준다. 즉, 개발 도중에 오류를 확인할 수 있다.
3. 생산성 증가

자바스크립트의 문제점 First

[1, 2, 3, 4] + false
//결과 : '1,2,3,4false'
  1. 배열이 완전히 사라진다.
  2. boolean인 false는 string이 된다.

자바스크립트의 문제점 Second

function divide(a, b){
	return a / b
}

divide(2, 3) //0.66666666666
divide("xxxxx") //NaN
  1. 자바스크립트가 이 함수를 올바르게 사용하도록 강제하지 않는다는 점이다.
  2. divide("xxxxx") divide는 입력값이 두 개인데 하나밖에 보내지 않았는데 실행된다.
  3. 틀린 타입의 입력값을 보냈는데도 함수가 실행된다.

결론 : 자바스크립트는 a와 b가 필수 입력값인지 선택사항인지 전혀 모른다.

3️⃣ 최악의 에러는 런타임 에러

런타임 에러는 콘솔 안에서 일어나는 에러이다.
런타임 에러는 유저의 컴퓨터에서 코드가 실행될 때만 발생한다.

자바스크립트는 유저가 코드를 실행했을 때야 비로소 에러가 있다는 걸 알 수 있다. 하지만, 타입스크립트에서 이러한 에러는 코드를 실행하기 전에 최소화시킬 수 있다.

타입스크립트 코드를 컴파일하면, 보호장치 없는 일반적인 자바스크립트 코드가 된다. 그리고 타입스크립트 코드에 에러가 있으면 그 코드는 자바스크립트로 컴파일되지 않는다. 이러한 기능이 유저가 코드를 실행하는 런타임에 발생하는게 아니고 개발중에 발생하는 에러이기 때문에 런타임에러를 피할 수 있다.

4️⃣ 타입스크립트 타입 시스템

TypeSciprt는 두가지 접근방식을 결합했다.

1. 타입추론

let a = "hello"

a= "bye"

a =1 //ts -> error & js -> error없음

❗️자바스크립트에서는 그냥 변수를 생성만 하면서 그 변수가 어떤 타입인지는 지정해주지 않아도 된다.

2. 구체적인 타입 명시

let b : boolean = false

❗️typeScript의 type checker에게 타입을 추론하는 것을 허용하고 싶다면 사용X

let c : number[] = []

c.push("1") //error

배열에 아무것도 들어있지 않을 때 타입스크립트가 추론을 못하기 때문에 명시적으로 표현해줘야된다.

데이터와 변수의 타입을 명시적으로 정의할 수 있다. 하지만 그냥 JavaScript처럼 변수만 생성하고 넘어가도 된다. 왜냐하면 TypeScript가 타입을 추론해 주기 때문이다.

결론 : 명시적 표현은 최소한으로 사용하는게 좋다.
즉, 타입스크립트가 추론하는게 더 좋다.


5️⃣ 타입별칭(Type Aliases)

특정 타입이나 인터페이스를 참조할 수 있는 타입 변수를 의미한다.
타입별칭을 사용하여 객체 타입뿐만 아니라 모든 타입에 이름을 지정할 수 있다.

ex)

//string 타입을 사용할 때
const name : string = 'capt';

//타입 별칭을 사용할 때
type MyName = string;
const name : MyName = 'capt';

6️⃣ 선택적 프로퍼티(Optional Properties)

인터페이스의 모든 프로퍼티가 필요한 것은 아니다. 어떤 조건에서만 존재하거나 아예 존재하지 않을 수 있다. 그렇기 때문에 선택적 프로퍼티들을 사용하여 객체 안의 몇 개의 프로퍼티만 채워 함수를 전달하는 option bags같은 패턴을 만들 때 유용하다.

선택적 프로퍼티를 가지는 인터페이스는 다른 인터페이스와 비슷하게 작성되고, 선택적 프로퍼티는 선언에서 프로퍼티 이름 끝에 ?를 붙여 표시한다.

참고 자료

ex)
선택적 프로퍼티를 사용하지 않을 경우 → ❗️에러 발생

ex)
선택적 프로퍼티를 사용할 경우 → 에러 없음
? 추가

type Player = {
    name : string,
    age ?: number
}

const nico : Player = {
    name : "nico"
}

const lynn : Player = {
    name : "lynn",
    age : 12
}

7️⃣ 함수의 return 타입을 지정

예제)

//type Aliases 사용
type Name = string;
type Age = number;

type Player ={
	name : Name,
  	age ?: Age
}

function playerMaker(name : string){
	return {
		name
    }
}

const nico = playerMaker("nico")
nico.age = 12 //error

nico 객체에 age를 추가하면 에러가 발생한다.

이유 : playerMaker는 string인 name이라는 요소만 있는 object를 return하고 있기 때문이다. 따로 return 값을 설정해주어야 한다.

해결방법
TypeScript에게 playerMaker 함수는 Player 타입을 return하고 있다고 말해주어야 한다.

일반함수 return 타입 지정

//type Aliases 사용
type Name = string;
type Age = number;

type Player ={
	name : Name,
  	age ?: Age
}

function playerMaker(name : string) : Player{
	return {
		name
    }
}

const nico = playerMaker("nico")
nico.age = 12

화살표 함수 return 타입 지정

type Name = string;
type Age = number;

type Player ={
	name : Name,
  	age ?: Age
}

const playerMaker = (name : string) : Player => ({ name })

const nico = playerMaker("nico")

nico.age = 12
typescript에서
let resultPhrase = 'Result is: ';
resultPhrase = 0; // 이 부분에서 에러가 발생한다.

타입추론에 의해서 resultPhrase는 스트링이 올꺼라고 예상했다.

8️⃣ Tuple

  • 정해진 갯수의 요소를 가져야 하는 array를 지정할 수 있다.
  • 원하는 순서에 맞는 타입을 가질 수 있다.
  • 자바스크립트에서는 존재하지 않는다.
const player : [string, number, boolean] = ["nico",1,true]

player[0] = "hi"

9️⃣ any

  • TypeScript에서 빠져나오기 위한 방법.
  • any는 모든 것을 비활성화.
const q: any[] = [1, 2, 3, 4];
const z: any = true;
q + z; //에러발생 안됨.

🔟 union type

'이거 혹은 저거'와 같은 타입을 유니언타입이라고 한다.
두가지 타입을 설정할 때 사용한다.

  1. 변수 타입 사용
let name : string | number = "kim";
let age : (string | number) = 100;
  1. array, object 사용
let arr : (number | string)[] = [1, '2', 3];
let obj : { data : (string | number) } = { data : '123' };

매개변수를 유연하게 받을 수 있다.
어떤 타입을 받느냐에 따라 함수에 다른 로직이 필요할 수 있다. 이럴 때 유니언 타입을 사용한다.

// 유니언타입 사용
function combine(input1: number | string, input2: number | string) {
  let result;
  if (typeof input1 === 'number' && typeof input2 === 'number') {
    result = input1 + input2;
  } else {
    result = input1.toString() + input2.toString();
  }
  return result;
}

const combinedAges = combine(30, 26);
console.log(combinedAges);

const combinedNames = combine('Max', 'Anna');
console.log(combinedNames);
  • 유니언 타입을 사용한다고 해서 이렇게 런타임에서 타입을 검사하는 과정이 항상 필요하지는 않다. 하지만 주로 필요하긴하다. 런타임 타입 검사 없이 유니언 타입을 사용하는 상황도 있다. 어떤 로직을 작성하냐에 따라 다르다.

유니온 타입은 타입2개를 합쳐서 새로운 타입을 만들어냄

ex1)

  • string 타입 + 1(허용)
  • number 타입 + 1(허용)
  • string | number 타입 + 1(불가능)

왜 타입이 맞는데 +1이 안되는것?
타입스크립트는 타입 엄격한거 좋아한다.

1️⃣1️⃣ 리터럴타입

리터럴 타입은 특정 변수나 매개변수가 어떤 타입이어야 하는지 정의하는게 아니다.
숫자나 문자열이라고 하는게 아니라 정확히 어떤 값이어야 하는지 정의하는 것이다.
단점은 개발자로서 리터럴타입을 기억해야한다.
리터럴 타입을 유니언 타입으로 묶는 것이다.

resultConversion : 'as-number' | 'as-text'
리터럴 타입은 string이나 number와 같은 핵심 타입을 바탕으로 하지만 특정 버전의 타입을 사용할 수 있다. 예) 특정 문자열

1️⃣2️⃣ 타입알리어스 / 사용자 정의 타입

resultConversion : 'as-number' | 'as-text'
유니언 타입을 사용할 때 이렇게 계속 반복해서 적는 것은 번거롭다.

그렇기 때문에 type alias를 사용하면 된다.

1️⃣3️⃣ 함수의 반환 타입 및 "무효"

undefined
자바스크립트에서 실제로 어떤 값이다.
즉, 존재하지 않는 속성이나 객체에 접근할 때 나타나는 값이다.

기술적으로
void가 undefined를 반환하고 있다는 것이다.

헷갈리는 점
undefined 자체가 타입스크립의 타입이라는 것이다.
undefined를 타입으로 사용할 수 있다.

function printResult(num: number) : undefined{
    console.log('Result ' + num);
}

printResult(add(5,12));

단, 함수가 아무것도 반환하지 않을때 void는 쓸 수 있지만 undefined는 못쓴다.
void는 명시적으로 이 함수에 반환 구문이 없다고 알려주는 것이다.

function printResult(num: number) : undefined{
    console.log('Result ' + num);
  	return
}

printResult(add(5,12));

위 코드는 undefined라고 하면 타입스크립트는 반환 구문이 있지만 아무것도 반환하지 않는다고 이해한다. 오류가 발생하지 않는다.

자바스크립트 관점에서는 아래 두 코드 본질적으로 동일하다.

function printResult(num: number) : undefined{
    console.log('Result ' + num);
}

printResult(add(5,12));
function printResult(num: number) : undefined{
    console.log('Result ' + num);
  	return
}

printResult(add(5,12));

하지만 타입스크립트에서는 다르다. 그래서 반환 구문이 없을 때는 void를 쓰고 거의 쓸일이 없지만 반환 구문은 있지만 실제로 아무 값도 반환하지 않을 때는 undefined를 쓰면 된다. 이건 드믄 경우이다. 그냥 void를 사용해도 된다.

1️⃣4️⃣ any

타입 체크 해제 기능

1️⃣5️⃣ 함수타입 및 콜백

콜백 함수를 정의 시 장점
함수 안에서 콜백을 전달하면 타입스크립트는 결과가 숫자라는 것을 추론한다.

단, 타입스크립트가 잡지 않는 오류가 있다. 반환이다....
이것은 타입스크립트에서 버그나 실수가 아니다.
콜백 타입을 void라고 명시함으로써 여기에서 반환되는 결과를 무시하겠다고 의도적으로 밝힌다.

function add(n1: number, n2: number) {
  return n1 + n2;
}

function printResult(num: number): void {
  console.log('Result: ' + num);
}

function addAndHandle(n1: number, n2: number, cb: (num: number) => void) {
  const result = n1 + n2;
  cb(result);
}

printResult(add(5, 12));

let combineValues: (a: number, b: number) => number;

combineValues = add;
// combineValues = printResult;
// combineValues = 5;

console.log(combineValues(8, 8));

// let someValue: undefined;

addAndHandle(10, 20, (result) => {
  console.log(result);
});

퀴즈
아래 코드는 컴파일을 통과할 수 있는가?

function sendRequest(data: string, cb: (response:any) => void) {
	return cb({data: 'Hi there!'});
}

sendRequest('Send this!', (response) => {
	console.log(response);
  	return true;
})

통과할 수 있다.
콜백 함수는 자신이 전달되는 인수가 반환 값을 기대하지 않는 경우에도 값을 반환할 수 있다.

1️⃣6️⃣ unknown

변수의 타입을 미리 알지 못할 때 사용

  • TypeScript로 부터 보호받게 되어 어떤 작업을 하려면 이 변수의 타입을먼저 확인하는 방식으로 작동한다.
  • unknown 타입의 값을 타입이 정해진 변수에 할당하기 위해서는 이렇게 별도의 확인 작업이 필요하다.
  • any를 사용하는것 보다 낫다.

type of a가 number인지 확인하는 코드 작성

let a: unknown;

if (typeof a === "number") {
  let b = a + 1;
}
if (typeof a === "string") {
  let b = a.toUpperCase();
}

1️⃣7️⃣ never

never는 함수가 절대로 return 하지 않을 때 발생한다.

❗️많이 사용하지는 않는다.

함수에서 exception(예외) 발생할 때

function hello():never{
  	//return "X" //never 타입을 사용했기 때문에 
	throw new Error("X");
}

활용 - else{ name }은 절대 실행 되지 않는다.

function hello(name: string | number) {
  if (typeof name === "string") {
    name;
  } else if (typeof name === "number") {
    name;
  } else {
    //코드 작동 X
    name;
  } //여기에 뭘 작성하든 이 타입은 never가 될 거다.
}

1️⃣8️⃣ readonly

  • immutability(불변성)을 가질 수 있다.
  • 자바스크립트에서는 존재하지 않는다.
  • 자바스크립트에서는 일반 배열이다.
const names: readonly string[] = ["1", "2"];
names.push("3"); //readonly 때문에 push불가능.
//error message : Property 'push' does not exist on type 'readonly string[]'.
 
profile
오늘보단 내일이 강한 개발자입니다!🧑🏻‍💻
post-custom-banner

0개의 댓글