TypeScript 개괄

박다영·2023년 1월 16일
0

javascript

목록 보기
14/15

터미널 명령어

mkdir : make directory : 폴더 생성
code . : vscode 켜기
npm init -y : 프로젝트 초기 설정을 하겠다. package.json 깔림
npm install typescript : 해당 프로젝트에서만 타입스크립트 설치
npm -g install typescript : 타입스크립트 전역적으로 설치
npx : 사용할 모듈을 로컬에 저장하지 않고 매번 최신 버전의 파일을 불러와 사용한 다음 파일을 다시 없애는 방식
tsc : tsc 타입스크립트 컴파일러
npx tsc -init : tsc 타입스크립트 컴파일러를 해당 파일 혹은 전역에 저장하지 않고 그냥 한번 가져와서 쓰고 버리겠다. tsconfig.json 깔림
touch filename : 파일 만들기 (Ex: touch hello.ts)
npm install -g ts-node : 타스를 자스로 변환해서 출력할 수 있게 해주는 라이브러리 설치
ts-node ./filename : ts파일 출력 (Ex: ts-node ./example)


tsconfig.json

가장 중요한 두 가지 target & module
target : 타입스크립트를 여기에 입력된 버전의 자바스크립트로 번역하겠다. (ES2016, ES2015)
module : 타스 > 자스 로 전환되는 과정에서 import 문법 정하는 곳 (commonjs, ES2015, ESNext 등)


타스를 자스로 컴파일해야하는 이유

브라우저는 타스를 이해하지 못하기 때문.
브라우저가 이해하는 것 : html, css, js


기본 타입

string / number / boolean /
array / tuple /
any / void / null / undefined / never

// String
let str: string = 'Typescript';
let fullName: string = 'Kelly';
let sentence: string = `my name is ${fullName}.`;

// Number
// 2진수, 8진수, 10진수, 16진수 지원
let binary: number = 0b1010; // 2진수, 0b-
let octal: number = 0o744; // 8진수, 0o-
let decimal: number = 6; //10진수
let hex: number = 0xf00d; // 16진수, 0x-

// Boolean
let isTrue: boolean = true;
let isFalse: boolean = false;

// Array
let strArr: string[] = ['1', '2', '3'];
let strArr2: Array<string> = ['1', '2', '3'];
let numArr: number[] = [1, 2, 3];
let numArr2: Array<number> = [1, 2, 3];
let boolArr: boolean[] = [true, false, true];
let boolArr2: Array<boolean> = [true, false, true];

// Tuple
// ~개의 요소로 된 집합, 요소의 타입과 갯수가 고정된 배열
let x: [string, number];
x = [1, 'hi']; // 에러
x = ['hi', 1];
console.log(x[0], x[1]); // hi 1
x[2] = 'world'; // 에러, 정해진 배열의 길이를 뛰어넘음
let tuple: [string, number, boolean] = ['str', 1, false];

// Any
// 어떤 타입을 가진 값이든 다 들어갈 수 있는 것, 자스랑 비슷함
let string: any = 'hi';
string = 13;
string = 'abc';
string = true;
string = {};

// Void
// 함수 내에 리턴값이 없을 경우 반환값없음을 알려주는 용도의 타입, 변수 타입으로는 사용 안함
function d(): void {
  console.log('d');
}

// null, undefined
// 변수에 할당할 값이 null, undefined 뿐이라 주로 unionType 활용시 많이 쓰임
let e: null = null;
let f: undefined = undefined;
let unionType: number | null = 123; // number 와 null 둘 다 할당 가능

// Never
// 함수가 끝까지 실행되지 않거나 함수가 비정상적으로 종료되었음을 의미
function g(): never {
  while (true) {} // 실행 멈춤
}
function h(): naver {
  throw new Error('Error'); // 에러발생으로 비정상적으로 종료
}

함수 타입

기본 / 리턴값 타입 생략 / 화살표 함수 / 반환값이 없는 함수 /
Optional Parameter / Default Parameter / Rest Parameter

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

//  반환값의 타입은 추론이 가능해서 생략한 함수
function add2(n1: number, n2: number) {
  return n1 + n2;
}

// 화살표 함수
const add3 = (n1: number, n2: number) => {
  return n1 + n2;
};

// 반환값이 없는 함수
function printResult(num: number): void {
  console.log('Result' + num);
}

// Optional Parameter
// 조건문 함수와 '?'(:또는)붙여서 만드는 옵셔널 파라미터
// optional parameter에 아무 값이 할당되지 않았을 때, undefined 됨
// optional parameter는 required parameter 앞에 위치할 수 없음
function add4(n1: number, n2?: number) {
  if (!n2) return n1;
  return n1 + n2;
}
const a2 = add4(1, 2);
const b2 = add4(10, 20, 30); // 에러
const c2 = add4(10); // n2? 일때만 에러 안남

// Default Parameter
// 자스의 기능, default parameter에 아무 값이 할당되지 않았을 때, 설정해둔 값이 됨
function add5(n1: number, n2: number = 2) {
  return n1 + n2;
}
const f2 = add5(10); // 2번째 파라미터가 없어서 n2값이 2로 초기화됨
console.log(f2); // 12

// Rest Parameter
// 자스의 기능, 나머지의 역할을 하는 파라미터
// 남는 파라미터들을 배열로 만들어줌
// 처음이나 중간에는 올 수 없고, 함수 파라미터의 마지막에만 올 수 있음
function add6(n1: number, ...nums: number[]) {
  let totalOfNums = 0;
  for (let key in nums) {
    totalOfNums += nums[key];
  }
  return n1 + totalOfNums;
}
const result = add6(10, 20, 30, 40); //nums = [20,30,40]
console.log(result); // 100

이넘 enum 타입

숫자형 / 문자형 / 복합형

// 이넘 enum 타입
// 키 값으로 밸류를 불러올 수 있음 (.key 혹은 ['key'])

// 숫자형 이넘
// 인덱스처럼 다음순서로 가면 +1 씩 증가하는 순서 숫자를 가지고 있고,
// 안의 멤버 중 하나의 값을 수동으로 바꿔줄 수 있음
enum Direction {
  Up,
  Down = 100,
  Left,
  Right,
}

console.log(Direction.Up, Direction.Down, Direction.Left); // 0 100 101
const up: Direction = Direction.Up;
console.log(up); // 0
const leftOrRight: Direction.Left | Direction.Right = Direction.Left;
console.log(leftOrRight); // 101
console.log(Direction[100]); // Down

const ex1 = Direction['Down']; // 100
const ex2 = Direction.Down; // 100

// 문자형 이넘
// 이넘값 전부 특정 문자 또는 다른 이넘 멤버의 값으로 초기화 해야함
// 숫자형 이넘과 다르게 +1 씩 증가하는 것이 없음
enum Direction2 {
  Up = 'Up',
  Down = 'Down',
  Left = 'Left',
  Right = 'Right',
}
enum Language {
  Korean = 'ko',
  English = 'en',
  Japanese = 'jp',
}
const ex3 = Language['Korean']; // "ko"
const ex4 = Language.Korean; // "ko"

// 복합형 이넘 (권고하지 않음)
// 숫자형 이넘과 문자형 이넘을 혼용사용하나 유지보수에 혼란줄 수 있음
enum BooleanLikeHeterogeneousEnum {
  No = 0,
  Yes = 'Yes',
}

유니온 타입

// 유니온 타입 문법 (A || B)
// or 연산자와 마찬가지의 의미 (~이거나)
// | : 파이프 연산자
const printOut = (input: string | number) => {
  console.log(input);
}; // 문자열타입 혹은 숫자타입을 input 에 할당할 수 있음

// 유니온 타입의 장점
// 다른 타입을 혼용해서 쓰고자 할 때 유용하다
function getAge(age: number | string) {
  if (typeof age === 'number') {
    age.toFixed(); // 숫자 관련 메서드
    return age;
  }
  if (typeof age === 'string') {
    return age;
  }
}
function padLeft(value: string, padding: string | number) {
  if (typeof padding === 'number') {
    return Array(padding + 1).join(' ') + value;
  }
  if (typeof padding === 'string') {
    return padding + value;
  }
  throw new Error(`Expected string or number, got'${padding}.`);
}
console.log(padLeft('Hello World', 4)); // "    Hello World"
console.log(padLeft('Hello World', '!!!')); // "!!!Hello World"
console.log(padLeft('Hello World', true)); // 에러

타입 별칭 Type Alias

// 기존에는 새로운 값이 생길 때마다 하나하나 다 넣어줘야 하는점이 불편했음
const hero: { name: string; power: number; height: number } = {
  name: '슈퍼맨',
  power: 1000,
  height: 190,
};
const printHero = (hero: { name: string; power: number; height: number }) => {
  console.log(hero.name, hero.power);
};
printHero(hero);

// 타입별칭을 만들어 놓으면, 타입 속 내용만 수정하면 자동으로 연결된 부분 에러를 찾아줌
// 현업에서는 타입을 따로 적은 파일을 밖으로 분리하고 import 해오는 식으로 사용
type Hero = {
  name: string;
  power: number;
  height: number;
  gender: '남' | '여';
};
const hero1: Hero = {
  name: '슈퍼맨',
  power: 1000,
  height: 190,
  gender: '남',
};
const printHero1 = (hero: Hero) => {
  console.log(hero.name, hero.power);
};

인터페이스와 intersection Type

// 인터페이스 interface
// 다른 언어에서 인테페이스는 class 구현 전 필요한 메서드를 정의하기 위해 쓰임
// 타스에서는 더 다양한 것들을 정리

// 인터페이스로 타입 정의하는 방법
// 기본 정의
interface Person1 {
  name1: string;
  age1: number;
}
const person1: Person = { name1: 'js', age1: 20 };
const person11: Person = { name1: 'js', age1: 'twenty' }; // 에러

// 선택속성
// 함수타입에서 배운 옵셔널 파라미터와 유사
interface Person2 {
  name2: string;
  age2?: number;
}
const person2: Person2 = { name2: 'js' };
console.log(person2.name);

// Read Only 속성
// 인터페이스로 객체를 처음 생성할때만 값을 할당 가능
// 그 이후에는 변경이 불가능한 속성
interface Person3 {
  readonly name3: string;
  age3?: number;
}
const person3: Person3 = { name3: 'js' };
person3.name3 = 'lij'; // 에러
let readonlyArr: ReadonlyArray<number> = [1, 2, 3];
readonlyArr.push(4); // 에러
readonlyArr[0] = 100; // 에러

// 인덱스 index 타입
// 인터페이스에서 속성의 이름을 구체적으로 정의하지 않고, 어떤 값의 타입만 정의하는 것
interface Person4 {
  readonly name4: string;
  [key: string]: number | string;
  // 인덱스 key 에 어떤 string 이든 들어올 수 있고,
  // value 에는 string 또는 number가 들어올 수 있다.
  // key는 무조건 string, number만 들어올 수 있음
}
const p1: Person4 = { name4: 'js', birthDay: '비밀', age: 20 };

// 함수 타입
interface Print {
  (name: string, age: number): string;
}
// type Print = (name: string; age: number) => string; 과 동일
const getNameAndAge: Print = function (name5, age5) {
  return `name: ${name5}, age:${age5}`;
};

// 인터페이스 확장
interface Person {
  name: string;
  age: number;
}
interface Korean extends Person {
  birth: 'KDR';
}
interface Korean {
  name: string;
  age: number;
  birth: 'KDR';
}
interface Developer {
  job: 'developer';
}
interface KorAndDev extends Korean, Developer {}
interface KorAndDev {
  name: string;
  age: number;
  birth: 'KDR';
  job: 'developer';
}

// intersection Type
// & 여러 타입을 모두 만족하는 하나의 타입
interface Person {
  name: string;
  age: number;
}
interface Developer {
  name: string;
  skill: string;
}
type DevJob = Person & Developer;
const nbcPerson: DevJob = {
  name: 'a',
  age: 20,
  skill: 'ts',
};

Type과 Interface의 차이

인터페이스는 확장이 가능하고, 타입은 확장이 불가능하다.
때문에 type보다 interface를 선언해 사용하는 것을 추천


제네릭

// 타입을 마치 함수의 파라미터처럼 사용하는 것
// 여러타입이 나올 수 있는 공통함수에서 많이 쓰임
function getText<T>(text: T): T {
  return text;
}
getText<string>('hi');
getText('hi'); // 생략 가능(명시적 역할)
getText<number>(10);
getText<boolean>(true);
function getItemArray<T>(arr: T[], index: number): T {
  return arr[index];
}
function pushItemArray<T>(arr: T[], item: T): void {
  arr.push(item);
}
const techStack = ['js', 'react'];
getItemArray(techStack, 0); // 'js'
pushItemArray(techStack, 'ts'); // ['js', 'react', 'ts']

// 제네릭 타입 변수
function printedOut<T>(input: T[]): T[] {
  console.log(input.length);
  return input;
}
printedOut([1, 2, 3]);

// 제네릭 제약 조건
interface LengthMise {
  length: number;
}
function printedIn<T extends LengthMise>(input: T): T {
  console.log(input.length);
  return input;
}
printedIn(10); // 에러
printedIn({ length: 0, value: 'hi' });

타입 추론

타입을 넣어주지 않아도 자동으로 각 타입을 인식하는 것

// let 으로 선언된 변수는 재할당이 가능해 융통성있게 타입이 결정되는데,
let a = 123;
let b = 'abc ';
a = 'abc'; // 에러
b = 123; // 에러

// const 로 선언된 변수는 재할당이 불가능해 엄격하게 타입이 결정됨.
const c1 = 123; // c1의 타입은 123
c1 = 124; // 에러

// Array
const arr = [1, 2, 3];
const [n1, n2, n3] = arr; // n1, n2, n3의 타입을 number임
arr.push['a']; // 에러

// Object
const obj = { numId: 1, stringId: '1' };
const { numId, stringId } = obj;
console.log(numId === stringId); //에러(비교불가, 자료형 다르니까)

// Function
// 같은 매개변수 자리에 다른 타입을 허용할 때
const func1 = (a: number | string = 'a', b = 1) => {
  return `${a}+${b}`;
};
func1(3, 6);
profile
개발과 디자인 두마리 토끼를!

0개의 댓글