TypeScript

SOO·2022년 10월 17일
0

basic

목록 보기
6/16

Why not JavaScript

Javascript
└ 매우 유연해서 에러를 잘 보여주지 않음
숫자 배열 + false → 배열이 사라지고 string으로 바뀜
함수의 인자가 잘못 들어가도 실행됨→ return값이 NaN일 뿐, 에러가 나지 않음
const a = { a: "A" };
a.hello();
실행 시 에러 발생 →실행 전에 에러 감지 불가

Typescript
└ 타입 안정성 → 버그 감소

How Typescript Works

타입스크립트 코드 테스트
https://www.typescriptlang.org/play

타입스크립트 핸드북
https://typescript-kr.github.io/pages/basic-types.html

타입스크립트 = Strongly typed programming
1.TypeScript는 JavaScript에 추가적인 구문을 추가하여 editor와의 단단한 통합을 지원합니다. editor에서 초기에 오류를 잡을 수 있습니다.

  1. TypeScript 코드는 JavaScript가 실행되는 모든 곳(브라우저, Node.js 또는 Deno 및 앱 등)에서 JavaScript로 변환가능

  2. TypeScript는 JavaScript를 이해하고 타입 추론(type inference)을 사용하여 추가 코드 없이도 훌륭한 도구를 제공

타입스크립트가 제공하는 보호장치는 타입스크립트 코드가 자바스크립트로 변환되기 전 발생함
타입스크립트가 먼저 우리코드 확인 후 변환된 자바스크립트안에서 ㅏㅂ보 같은 실수가 일어나지않게 확인해줌
타입스크립트가 에러가 날 것 같은 코드가 있으면 자바스크립트로 아예 컴파일 되지 않음

Implicit Types vs Explicit Types

  1. 데이터와 변수의 타입 명시적 정의(변수 선언 시 타입 정의)

let a: boolean = "x" → 🚫 boolean 타입에 string타입 할당 불가 알림

  1. 변수만 생성(타입 추론)
    let b = "hello" → b가 string 타입이라고 추론
    b = 1→ string 타입에 number타입 할당 불가 알림

Quiz

JavaScript is a type safe langauge. No

What happens if we run this code in JS: It will run

What is a runtime error? An error that happens while the code runs

What is Typescript compiled to? JavaScript Code

We always have to specify a type for our variables in Typescript.
No, Typescript can infer it sometimes

How do we set the type of a variable explicitly in TS?
const x : string = "hi"

Types of TS part One

let a :number[] =[1,2]

===

let a = [1,2]

const player: {
name:string, age? number}= {
name:"nico"
}

player는 object type, name은 string이고 age는 number이거나 undefined라고 되어있음

type Age = number;
type Name = string;
type Player={
name:Name,
age?:Age}
cont nico: Player={
name:"nico"}
function playerMaker(name:string){
return {
name
}
}
const nico = playerMaker("nico")
const playerMaker = (name:string) : Player => ({name})
const nico = playerMaker("nico")

readOnly
JavaScript에서는 mutability(변경 가능성)이 기본값이지만 타입스크립트에서는 readonly를 통해 읽기 전용으로 만들 수 있습니다.

interface Pizza {
readonly x: number;
}

let pizza: Pizza = { x: 1 };
pizza.x = 12; // error

Tuple
정해진 개수와 순서에 따라 배열 선언
const player: [string, number, boolean] = ["nico", 1, true]

any: 아무 타입, typeScript의 모든 보호장치를 비활성화 시킴
undefined: 선언X 할당X
null: 선언O 할당X

TypeScript에서 중요한건 TypeCheckerd와의 소통

Unknown

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

let a :unknown;

if(typeof a === 'number'){
let b = a+1
}

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

void

아무것도 return하지않는 함수를 대상으로 사용

function hello(){
console.log('x')}

never

함수가 절대 return하지 않을 때 발생
return하지 않고 오류를 발생시키는 함수


function hello():never{
return "x"
}
// 에러

function hello():never{
throw new Error("xxx")
}

Quiz

What is the syntax to type an array of booleans?

: boolean[]

For what do we use Type Aliases?

To create a new name for a type

What is the syntax to say that a function returns an array of strings?

function name(): string[]

Does the readonly from Typescript compile to JavaScript?No

Why do we use Tuples for?

To specify an array with a min. length and type positions

We should try to use any as much as possible.No

What happens when we use any? We escape the TS world

What do we have to do before using a variable of type unknown?
We have to first check with typeof

When do we use void? When a function does not return anything

When do we use never? When a path of code should never run

Call Signatures

type Add = (a:number, b:number) => number;

const add:Add = (a,b) => a+b

Overloading

오버로딩은 함수가 서로 다른 여러개의 call signatures를 가지고 있을 때 발생시킴

type Config = {
path:string, state:object}

type Push = {
	(path:string):void
    (config:Config):void
}


const push:Push = (config) => {
	if(typeof config === "string") {console.log(config)}
    else{
    console.log(config.path)
    }
}

Quiz

What is call signature? Is the type of the arguments and return value of a function

A call signature has the implementation of the function.No

Call Signatures will be compiled into Javascript No

We can use the same call signature for multiple functions. Yes

When does 'overloading' happen? When a function has multiple call signatures

When should we use function overloading? When the function should accept different argument types

Polymorphism

geneiric이란, 타입의 placeholder 같은거임
우리는 typescript로 placeholder를 작성할 수 있고,
그게 뭔지 추론해서 함수 사용

generic 사용법

  1. 타입스크립트에 generic을 사용하고 싶다고 알려줘야함
type SuperPrint = {<TypePlaceholder>(arr:TypePlaceholder[]):TypePlaceholder}

const superPrint:SuperPrint = (arr) => arr[0]

const a = superPrint([1,2,3,4]) // const superPrint: <number>(arr: number[]) => void
const b = superPrint([true, false, true])


<>안에 이름 맘대로

conclustion

type NicoExtra = { favFood:string;}

type NicoExtra = Player<{favFood:string}>

type NicoPlayer = Player<{NicoExtra}>

type Player<E> = { name: string extraInfo:E}

coding Challenge

// Last

type Last = <T>(items: T[]) => T;

const last: Last = (items) => items[items.length - 1];

const lastItem = last([1, 2, 3, 4, 5]);

console.log(lastItem);

// Prepend

type Prepend = <T>(items: T[], item: T) => T[];

const prepend: Prepend = (items, item) =>  [item, ...items]

const items = [1, 2, 3, 4, 5];

const newItems = prepend(items,0);

console.log(newItems)

Classes

class Player {
	constructor(
    	private firstName:string,
        private lastName:string,
      	public nickname;string
    ){}
}

const nico = new Player("nico", "las", "니꼬");

nico.firstName 이런식으로 쓰면 컴파일 x 왜냐 private이니까
private keyword는 오로지 typeScript가 너를 보호해주기 위해서만 사용하는 것

추상 클래스

abstract class User{
constructor(
    	private firstName:string,
        private lastName:string,
      	public nickname;string
    ){}
    
    abstract getNickName():void
    
    protected getFullName(){
    	return `${this.firstName} ${this.lastName}`
    }
}
class Player extends User{
	getNickName(){
 		console.log(this.nickname)
    }
 }

const nico = new Player("nico", "las", "니꼬");

nico.getFullName()

추상클래스는 오직 다른곳에서 상속만 받을 수 있는 클래스
추상메소드는 네가 추상 클래스를 상속받는 모든것들이 구현을 해야하는 메소드를 의미

type Words = { // 해시
[key: string]: (string | string[])
//객체의 property에 대해 모르지만 타입만을 알 때 유용하다
}
class Dict {
private words: Words
constructor() {
this.words = {}
}
add(word: Word) { // word는 Word 클래스의 인스턴스 타입.
if(!this.words[word.term]) {
// 사전에 없는 단어이면
this.words[word.term] = word.def;
}
}
find(term: string) {
return this.words[term];
}
// 단어를 삭제
rmv(term: string) {
delete this.words[term];
}
// 단어 이름 업데이트
update(oldTerm: string, newTerm: string) {
if(this.words.hasOwnProperty(oldTerm)) {
this.words[newTerm] = this.words[oldTerm];
delete this.words[oldTerm];
}
}
// 사전에 저장된 단어의 개수
size() {
return Object.keys(this.words).length;
}
// 모든 사전의 이름과 뜻 출력
all() {
for(let [key, value] of Object.entries(this.words)) {
console.log(`${key}: ${value}`)
}
}
}
// words는 initializer 없이 선언해주고 contructor에서 수동으로 초기화
// constructor에 인자로 넣어 constructor가 지정해주길 바라는 게 아니므로

// 각각의 단어에 대한 클래스
class Word {
constructor(public term: string, public def: (string| string[])) {}
// 단어 출력하는 메소드
toString() {
console.log(`${this.term}: [뜻] ${this.def}`);
}
// 단어 정의 추가
addDef(newDef : string) {
if(typeof this.def === 'string') {
this.def = [this.def, newDef]
} else {
this.def = [...this.def, newDef];
}
}
// 단어 정의 수정
updateDef(oldDef : string, newDef: string) {
if(typeof this.def === 'string') {
if(oldDef === this.def) this.def = newDef
} else {
this.def.filter(val => val !== oldDef);
this.def.push(newDef);
}
}
}
/** 출력 */
const kimchi = new Word("kimchi", "한국의 음식");
const tang = new Word("연근 갈비탕", "중국의 음식");
const sushi = new Word("스시", "일본의 음식");
kimchi.addDef("고춧가루로 배추를 버무려 숙성 및 발효시킨 음식")
kimchi.toString(); // kimchi: 한국의 음식,고춧가루로 배추를 버무려 숙성 및 발효시킨 음식
tang.toString() // 연근 갈비탕: 중국의 음식
sushi.updateDef("일본의 음식", "밥을 뭉쳐놓고 그 위에 재료를 얹어낸 음식");
sushi.toString(); // 스시: 밥을 뭉쳐놓고 그 위에 재료를 얹어낸 음식
const dict = new Dict();
dict.add(kimchi);
dict.add(tang);
dict.add(sushi);
dict.all()
// kimchi: 한국의 음식,고춧가루로 배추를 버무려 숙성 및 발효시킨 음식
// 연근 갈비탕: 중국의 음식
// 스시: 밥을 뭉쳐놓고 그 위에 재료를 얹어낸 음식
dict.find("kimchi");
// (2) ['한국의 음식', '고춧가루로 배추를 버무려 숙성 및 발효시킨 음식']
dict.size()
// 3
dict.update("kimchi", "김치")
dict.all()
// 연근 갈비탕: 중국의 음식
// 스시: 밥을 뭉쳐놓고 그 위에 재료를 얹어낸 음식
// 김치: 한국의 음식,고춧가루로 배추를 버무려 숙성 및 발효시킨 음식
dict.rmv("연근 갈비탕");
dict.all()
// 스시: 밥을 뭉쳐놓고 그 위에 재료를 얹어낸 음식
// 김치: 한국의 음식,고춧가루로 배추를 버무려 숙성 및 발효시킨 음식

coding challenge

type Words = {
[key: string]: string;
};

class Dict {
private words: Words;
constructor() {
this.words = {};
}

//추가
add(word: Word) {
if (this.words[word.term] === undefined) {
this.words[word.term] = word.get;
}
}

//정의 반환
get(term: string) {
return this.words[term];
}

//단어 업데이트
update(word: Word) {
if (this.words[word.term] !== undefined) {
this.words[word.term] = word.get;
}
}


//단어 삭제
del(term: string) {
if (this.words[term] !== undefined) {
delete this.words[term];
}
}

//단어 수
count(){
return Object.keys(this.words).length;
}

//모든
showAll() {
return Object.keys(this.words)
}
}

class Word {
constructor(public term: string, public get: string) {}
}


const baseball = new Word("baseball", "ball game on the mound");
const basketball = new Word("basketball", "ball game on the coart");
const dict = new Dict();

dict.add(baseball);
dict.add(basketball);
console.log(dict.get("baseball"));
console.log(dict.get("basketball"));

console.log(`사전 전체 단어 : ${dict.showAll()}`);

dict.update(new Word("basketball", "ball game on the court"));
console.log(dict.get("basketball"));


dict.del("baseball");
console.log(dict.get("baseball"));


console.log(`사전 전체 단어 : ${dict.showAll()}`);
console.log(`사전 전체 단어 갯수: ${dict.count()}`);

coding challenge

type Words = {
  [key: string]: string;
};

class Dict {
  private words: Words;
  constructor() {
    this.words = {};
  }
  add(term: string, definition: string) {
    if (!this.words[term]) {
      this.words[term] = definition;
    }
  }
  get(term: string) {
    return this.words[term];
  }
  delete(term: string) {
    delete this.words[term];
  }
  update(term: string, newDef: string) {
    if (this.words[term]) {
      this.words[term] = newDef;
    }
  }
  showAll() {
    Object.keys(this.words).forEach((term) =>
      console.log(`${term}: ${this.words[term]}`)
    );
  }
  count() {
    return Object.keys(this.words).length;
  }
}

const dictionary = new Dict();

dictionary.add("김치", "밋있는 한국 음식");
dictionary.showAll();
console.log(dictionary.count());
dictionary.update("김치", "밋있는 한국 음식!!!");
console.log(dictionary.get("김치"));
dictionary.delete("김치");
console.log(dictionary.count());

Interface

type Team = "red" | "blue"| "yellow"
type Health = 1|5|10

typeScript에게 오브젝트의 모양을 알려주는 방법엔 2가지가 있음

type Player = {
	nickname:string,
    team:Team
    health:Health
}

하나는 type을 쓰고, 이렇게 오브젝트의 모양을 써주는 방법이 있고

interface Player {
nickname:string
team:Team
health:Health
}

인터페이스는 타입스크립트에게 오브젝트의 모양을 설명해주는 하나의 목적으로만 사용 가능함

interface User{name:string}

intergace Player extends User{}

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

Interface part Two

protected는 추상 클래스로부터 상속받는 클래스들이 property에 접근하도록 해줌

abstract class User {
	constructor (
    	protected firstName:string,
        protected lastName:string
    ){}
    abstract sayHi(name:string):string
    abstract fullNmae():string
}
class Player extends User{
	fullName(){
    	return `${this.firstName} ${this.lastName}`
    }
    sayHi(name:string){
    	return `Hello ${name}. My name is ${this.fullName()}` 
    }
}

상속받는 클래스가 어떻게 동작해야할 지 일러주기 위해서 추상클래스를 사용함
추상클래스를 만들면 이게 js에서는 일반적인 클래스로 바뀌어버림

인터페이스는 컴파일하면 JS로 바뀌지 않고 사라짐

인터페이스는 고유한 사용처가 있고 클래스의 모양을 알려준다는 점에서 엄청 유용함

QUIZ

A readonly class property in TS will also be readonly in JS. No

Is this type: string[] the same as Array ? Yes

Is this code correct?

interface Sizes = "xs" | "s" | "m" | "l" | "xl"

No

type Player = {
    name:string,
    size:"xs" | "s" | "m" | "l" | "xl"
}

YES

What is the difference between a type and an interface?

Interfaces can only be used to type an object, a Type can be used for anytype.

What is the difference between an abstract class and a "normal" class?
We can't make an instance of an abstract class

And abstract class will become a normal class in JS
Yes

When we compile the code interfaces will dissapear. Yes

recap

타입을 쓰고 싶다면 type keyword를 쓰면 됨

Type ver.

type PlayerA= { name : string }
const playerA: PlayerA = {
  name:"nico"
  }

Interface Ver.

interface PlayerB {
  name:string}
  
const playerB: PlayerB= {name:"nico"}

어케 타입 상속? 또 다른 타입 하나를 만들어서 playAA 타입이 PlayerA 타입과 lastName을 가지는 오브젝트를 합친 거라고 알려줘야함

type PlayerA = {
  name:string }
  
type PlayerAA = PlayerA & {
  lastName:string
  } 
  
const playerA: PlayerAA = {
  name:"nico",
  lastName:"xxx"
  }

인터페이스 상속 방법

interface PlayerB{name:string}
  
interface PlayerBB extends PlayerB {lastName:string}
  
const playerB: PlayerB = {
	name:"nico",
  lastName:"xxx"
}  
  

Type Aliases과 인터페이스는 매우 유사하며 많은 경우 자유롭게 선택할 수 있음
인터페이스의 거의 모든 기능은 type에서 사용할 수 있으며, 주요 차이점은 type을 다시 열어 새 속성을 추가할 수 없는 것
반면 인터페이스는 항상 확장 가능

Adding new fields to an existing interface

interface Window {title:string}
  
interface Window  {ts:TypeScriptApi}
  
const src  = 'const a = "hello wolrd"';
window.ts.transpilemOdule(src,{});
  
type Window = {title:string}
type Window={ts:TypeScriptApi}
  

ERROR!

polymorphism

다형성은 다른 모양의 코드를 가질 수 있께 해주는 것
다형성을 이룰 수 있는 방법은 제네릭을 사용하는거임
제네릭은 placeholder type을 쓸 수 있도록 해줌
concrete type이 아니라 placeholder type

interface LocalStorageAPI<T> {
    [key:string]:T
}

class LocalStorage<T> {
    private storage:LocalStorageAPI<T> = {}
    set(key:string, value:T)
    {
        this.storage[key] = value;
    }
    remove(key:string) {
        delete this.storage[key]
    }
    get(key:string):T{
        return this.storage[key]
    }
    clear(){
        this.storage={}
    }
}

const stringStorage = new LocalStorage<string>
stringStorage.get("hi")

const booleanStorage = new LocalStorage<boolean>();
booleanStorage.get("xxx")

interface GeolocationAPI {
    
}

때가 되면 타입스크립트가 placeholder type을 concrete type으로 바꾸어 줄거야
이 T인 value를 string인 value로 바꿔주는거임

coding challenge

참고

LocalStorage API
먼저 로컬 스토리지에 들어갈 아이템들의 타입을 설정
이번에는 interface를 사용
interface의 경우 상속이 굉장히 용이한 타입 식별자

로컬 스토리지 내부에 저장되는 데이터는 key: value쌍의 값으로 저장
또한, 인풋의 타입이 어떻게 되느냐에 따라 아웃풋의 타입도 유동적으로 변할 수 있도록 제네릭을 함께 설정해주어 Items라는 타입을 만들었음.

다음으로 추상화 클래스를 만들어 볼 차례
추상화를 시킬 땐 abstract라는 키워드를 사용
앞서 만들었던 Items라는 타입을 protected 키워드를 이용해 오직 하위 클래스에서만 접근 가능하도록 items라는 객체 필드에 타입을 지정해주었음
그리고 나머지 메소드들 또한 전부 abstract로 연결시켜주었으며, 제네릭을 활용함

마지막으로 실제 API로 사용될 SuperStorage라는 임의의 이름을 가진 새로운 클래스를 만들고 extends라는 키워드를 이용해 앞서 만든 추상화 클래스를 상속시켜 주었음
모범 답안에서는 모든 메소드에 대해 접근이 가능하도록 public 키워드를 사용

GeoLocation API
overloading을 활용하는 챌린지
overloading은 글자 그대로 이름은 동일하되 서로 다른 타입들을 덧붙이는 것이라고 이해하면 쉬움

먼저 GeolocationCoordinates의 타입을 설정
GeoLocation은 사용자의 로컬 컴퓨터의 위치를 좌표 형식으로 나타내줌. 사용법에 있는 메소드로 전달된 파라미터들 중에 각각optionsObj, errors, option 등은 전부 객체 형태인 것을 유추할 수 있음. 그렇기 때문에 각각 GeoOptions, GeoError, GeolocationCoords 그리고 Position이라는 타입을 각각 만들어서 필요한 필드들이 담긴 타입을 만들었음

다음으로 successFn, errorFn의 콜백 함수에 대한 타입을 설정할 차례

앞서 만든 GeoOptions, GeoError, GeolocationCoords 그리고 Position을 successFn과 errorFn의 파라미터에 적용시킬 타입으로 사용함
그렇게 SuccessFunction과 ErrorFunction이라는 타입을 만들었음.
이후, 사용법에 제시된 getCurrentPosition()과 watchPosition() 메소드의 전체 타입을 지정하도록 함. 앞서 만든 SuccessFunction 타입과 ErrorFunction을 연결 지을 수 있도록 GetCurrentPosition과 WatchCurrentPosition 타입을 만든 후, return되는 타입을 설정해주고, 이를 하나로 묶은 GeolocationAPI라는 interface를 만듦. 추후에 상속을 해야하니까.

마지막으로 Geolocator라는 클래스를 만듦. 이것이 실제로 API로 사용될 클래스이며 GeolocationAPI 타입을 연결. getCurrentPosition()과 watchPosition() 메소드에서 전달되는 error와 options는 없을 수도 있기 때문에 ? 연산자를 통해 필수가 아닌 선택적인 요소로 바꾸었음

// LocalStorage Interface
abstract class LocalStorage<T> {
  protected items: Items<T>;
  constructor() {
    this.items = {};
  }
  abstract length(): number;
  abstract key(index: number): T;
  abstract getItem(key: string): T;
  abstract setItem(key: string, value: T): void;
  abstract removeItem(key: string): void;
  abstract clear(): void;
}
interface Items<T> {
  [key: string]: T;
}
class SuperStorage extends LocalStorage<string> {
  constructor() {
    super();
  }
  public key(index: number) {
    return Object.keys(this.items)[index];
  }
  public length() {
    return Object.keys(this.items).length;
  }
  public getItem(key: string) {
    return this.items[key];
  }
  public setItem(key: string, value: string) {
    this.items[key] = value;
  }
  public removeItem(key: string) {
    delete this.items[key];
  }
  public clear() {
    this.items = {};
  }
}

// Geolocation Interface
type GeolocationCoords = {
  latitude: number;
  longitude: number;
  altitude: number;
  accuracy: number;
  altitudeAccuracy: number;
  heading: number;
  speed: number;
};
type Position = {
  coords: GeolocationCoords;
};
type GeoError = {
  code: number;
  message: string;
};
type SuccessFunction = (position: Position) => void;
type ErrorFunction = (error: GeoError) => void;
type GeoOptions = {
  maximumAge: number;
  timeout: number;
  enableHighAccuracy: boolean;
};

type GetCurrentPosition = {
  (success: SuccessFunction): void;
  (success: SuccessFunction, error: ErrorFunction): void;
  (success: SuccessFunction, error: ErrorFunction, options: GeoOptions): void;
};

type WatchCurrentPosition = {
  (success: SuccessFunction): number;
  (success: SuccessFunction, error: ErrorFunction): number;
  (success: SuccessFunction, error: ErrorFunction, options: GeoOptions): number;
};

interface GeolocationAPI {
  getCurrentPosition: GetCurrentPosition;
  watchPosition: WatchCurrentPosition;
  clearWatch: (id: number) => void;
}

class Geolocator implements GeolocationAPI {
  getCurrentPosition: GetCurrentPosition = (
    success: SuccessFunction,
    error?: ErrorFunction,
    options?: GeoOptions
  ) => {
    return; // Implementation goes here :)
  };
  watchPosition: WatchCurrentPosition = (
    success: SuccessFunction,
    error?: ErrorFunction,
    options?: GeoOptions
  ) => {
    return 1; // Implementation goes here :)
  };
  clearWatch = (id: number) => {};
}

Targets

typescript설치
npm i -D typescript

package.json 초기화
npm init -y

tsconfig.json설정
디렉터리에 tsconfig.json 파일이 있으면 해당 디렉터리가 TypeScript 프로젝트의 루트임을 나타냅니다. tsconfig.json 파일은 프로젝트를 컴파일하는 데 필요한 루트 파일과 컴파일러 옵션을 지정합니다.
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#handbook-content

Target (기본값: ES3)
최신 브라우저는 모든 ES6 기능을 지원하므로 ES6는 좋은 선택입니다. 코드가 이전 환경에 배포된 경우 더 낮은 target을 설정하거나 최신 환경에서 코드 실행이 보장되는 경우 더 높은 target을 설정하도록 선택할 수 있습니다.
ex) 화살표 함수() => this는 ES5 이하이면 함수 표현식으로 바뀝니다.

특별한 ESNext 값은 TypeScript 버전이 지원하는 가장 높은 버전을 나타냅니다. 이 설정은 다른 TypeScript 버전 간에 동일한 의미가 아니며 업그레이드를 예측하기 어렵게 만들 수 있으므로 주의해서 사용해야 합니다.
https://www.typescriptlang.org/tsconfig#target

"build": "tsc" 또는 "npx tsc"

@ts-check
JavaScript 파일에서 오류를 활성화하려면 // @ts-check를 .js 파일의 첫 번째 줄에 추가하여 TypeScript가 오류를 발생시키도록 합니다. TypeScript는 여러 오류를 제공할 수 있습니다.
이러한 오류를 무시하고 싶다면 // @ts-ignore 또는 // @ts-expect-error를 추가하여 특정 줄의 오류를 무시할 수 있습니다.
https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check

JSDoc Reference
JSDoc 주석을 사용하여 JavaScript 파일에 type 정보를 제공할 수 있습니다. (자바스크립트 파일에서 타입 정보를 제공할 수 있습니다.)
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html

@param, @returns

/**
* @param {string} p1 - A string param.
* @param {string=} p2 - An optional param (Google Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @returns {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4) {
// 코드...
}

https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#param-and-returns

quiz

Inside of tsconfig.json what does the include property do?
It tells TS where to look for code to compile

Inside of tsconfig.json what does the outDir property do?
It tells TS where to put the output code

Inside of tsconfig.json what does the target property do?
It specifies the version of JS we want to compile to the to

Inside of tsconfig.json what does the lib property do?
It specifies what environment the code is goin to run on

What is a Type Definition file?
A TS file with comments that explains to TS the types of JS code

Can we use Typescript and Javascript in the same project?
Yes

What does //@ts-check do?
It tells TS to type check JS files

Can we use JSDoc on any JS file? Yes

DefinitelyTyped

TypeScript type 정의를 위한 리포지토리입니다.
https://github.com/DefinitelyTyped/DefinitelyTyped

0개의 댓글