TS스터디 이펙티브 item1~3

온호성·2023년 3월 22일
0

😲item1 타입스크립트와 자바스크립트의 관계 이해하기

-타입스크립트는 자바스크립트의 상위집합이다.

  • 모든 자바스크립트 프로그램은 이미 타입스크립트 프로그램이다.

  • 타입스크립트는 별도의 문법을 가지고 있기 때문에 일반적으로는 유효한
    자바스크립트 프로그램이 아니다.

  • 자바스크립트 파일이 js(또는 .jsx)확장자를 사용하는 반면
    타입스크립트 파일은 ts(또는 .tsx) 확장자를 사용한다.

  • 모든 자바스크립트는 타입스크립트이지만, 모든 타입스크립트가 자바스크립트는 아니다.

- Ts vs Js

ts

function greet(who: string) {
 console.log('Hello', who);
}

js

function greet(who: string) {
                  ^
SyntaxError: Unexpected token :

string은 타입스크립트에서 쓰이는 타입구문이다.
따라서 js에서 사용하게 되면 문법 오류가 난다.

- 타입체커

js

let city = 'new york city';
console.log(city.toUppercase());

TypeError: city.toUppercase is not a function;

ts

let city = 'new york city';
console.log(city.toUppercase());
				// ~~~~~~~~~~~~'toUppercase' 속성이 'string' 형식에 없습니다.
               //				'toUpperCase'를 사용하시겠습니까?

이와같이 앞 js 코드에는 타입 구문이 없지만, ts의 타입 체커는 문제점을 찾아 낸다. -city 변수가 문자열이라는 것을 알려 주지 않아도 타입스크립트는 초깃값으로 부터 타입을 추론한다.
-타입 시스템의 목표중 하나가 런타임에 오류를 발생시킬 코드를 미리 찾아내는 것이기 때문에 이로써 타입스크립트는 정적타입 시스템이라 할 수 있다.

그러나 타입 체커가 모든 오류를 찾아내지는 않는다 오류가 발생하지는 않지만 의도와 다르게 동작하는 코드도 있다.

  • 위와 같이 모든 자바스크립트는 타입스크립트이지만, 일부 자바스크립트(그리고 타입스크립트)만이 타입 체크를 통과한다.

타입스크립트 타입 시스템은 자바스크립트의 런타임 동작을 모델링 한다.

const x = 2 + '3'; // 정상, string 타입입니다.
const y = '2' + 3; // 정상, string 타입입니다.

위 예제는 다른 언어였다면 런타임 오류가 뜨는 코드이지만, 타입스크립트의 타입 체커는 정상으로 인식한다 두 줄 모두 문자열"23"이 되는 자바스크립트 런타임 동작으로 모델링 되는데 반대로 정상 동작하는 코드에 오류를 표시하기도 한다.

😥정상 동작하는 코드에 오류 표시하는 경우

const a = null + 7; // 자바스크립트에서는 a값이 7이 됩니다.
		// ~~~ '+' 연산자를 ... 형식에 적용할 수 없습니다.
const b = [] + 12; // 자바스크립트에서는 b값이 '12'가 됩니다.
		// ~~~~~~~ '+' 연산자를 ... 형식에 적용할 수 없습니다.
alert('Hello', 'TypeScript'); // "Hello" 경고를 표시합니다.
			// ~~~~~~~~~~~~~ 0-1개의 인수가 필요한데 2개를 가져왔습니다. 

😆item2 타입스크립트 설정 이해하기

타입스크립트는 어떻게 설정하느냐에 따라 완전히 다른 언어처럼 느껴 질 수 있는데 noImplicitAny 와 strictNullChecks 를 이해해야 한다.

noImplicitAny는 변수들이 미리 정의된 타입을 가져야하는지 여부를 제어한다는 설정인데 "암시적 any가 금지된다" 는 설정이다 타입스크립트는 타입 정보를 가질 때 가장 효과적이기 때문에 이 옵션은 되도록 설정하도록 권장되어 진다.

  • 자바스크립트 프로젝트를 타입스크립트로 마이그레이션 하는 경우가 아니라면 noImplicitAny를 설정하는 것이 좋다.

  • 새 프로젝트를 시작한다면 처음부터 noImplicitAny를 설정하여 코드를 작성 할 때마다 타입을 명시하도록 해야 한다.
    ->타입스크립트가 문제를 발견하기 수월해지고, 코드의 가독성이 좋아지며, 개발자의 생산성이 향상된다.

    strictNullChecks는 null과 undefined가 모든 타입에서 허용되는지 확인하는 설정이다. null, undefined 관련된 오류를 잡아 내는 데 많은 도움이 되지만, 코드 작성이 어려워진다 새 프로젝트라면 설정하는게 좋지만 마이그레이션하는 프로젝트라면 힘들어 질 수 있다.

  • 새 프로젝트를 시작한다면 가급적 strictNullChecks를 설정하는 것이 좋지만, 타입스크립트가 처음이거나 자바스크립트 코드를 마이그레이션하는 중이라면 설정하지 않아도 괜찮다.

  • strictNullChecks를 설정하려면 noImplicitAny를 먼전 설정해야 한다.

✅위에 두 설정이 가장 핵심적인 설정이며, 이설정들과 또 훨씬 더 엄격하게 타입스크립트를 사용하고 싶다면 strict설정을 하면된다.

😁item3 코드 생성과 타입이 관계없음을 이해하기

타입 스크립트 컴파일러의 두가지 역할이 있는데

  • 최신 ts, js를 브라우저에서 동작할 수 있도록 구버전의 자바스크립트로 *트랜스 파일(transfile)한다.
  • 코드의 타입 오류를 체크한다.

다시말해 타입스크립트가 자바스크립트로 변활될 때 코드 내의 타입에는 영향을 주지 않는다. 또한 그 자바스크립트의 실행 시점에도 타입은 영향을 미치지 않는다

let x = "hello";
x = 1234;
// ~ number 형식은 string에 할당될 수 업습니다.

// tsc test.ts ->

// test.js
let x = "hello";
x = 1234;
  • interface 등의 타입은 컴파일 과정중에 제거되기 때문에 런타임 시점에서는 아무 역활을 하지 않는다.
interface Car {
  name: string;
}

interface Truck extends Car {
  weight: number;
}

type Vehicle = Car | Truck;

function foo(ele: Vehicle) {
  if (ele instanceof Truck) {
    return ele.weight;
  } else {
    return ele.weight;
  }
}
  • instanceof는 결국 ele 가 Truck이라는 생성자에 해당 값이 존재하는지를 판별하는 것인데

  • Truck은 오로지 type의 역활만을 하고 type은 런타임환경에서는 제거된 상태이다.

    그렇기 때문에 런타임환경에서는 아무역활을 하지 못한다.

✅타입 연산은 런타임에 영향을 주지 않는다

string 또는 nuber 타입인 값을 항상 number로 정제하는 경우를 가정해 보면 다음 코드는 타입 체커를 통과하지만 잘못된 방법을 사용하였다.

function asNumber(val: number | string): number {
 return val as number;
}

이 코드는 다음 js코드로 변환된다.

function asNumber(val) {
  return val;
}

코드에 아무런 정돈한 과정이 없다. as number는 타입 연산이고 런타임 동작에는 아무런 영향을 미치지 않는데 값을 정제하기 위해서는 런타임의 타입을 체크하고 자바스크립트 연산을 통해 변환을 수행해야 한다.🔽

function asNumber(val: number | string): number {
  return typeof(val) === 'string' ? Number(val) : val;
}

✅런타임 타입은 선언되 타입과 다를 수 있다.

function setLightSwitch(value: boolean) {
  switch (value) {
    case true:
      turnLightOn();
      break;
    case false:
      turnLightOff();
      break;
    default:
      console.log(`I'm afraid I can't do that.`);
  }
}

위 함수를 보고 마지막 consol.log문이 실행되나 생각해보면
타입스크립트는 일반적으로 실행되지 못하는 dead코드를 찾아 내지만 위 코드에서는 찾아내지 못한다.

위 마지막 consol.log문을 실행할려면 어떻게 해야할까
=> 위 코드의 value: boolean에서 : boolean은 타입 선언문이다. 만약 value가 문자열이라면 default 케이스가 실행될 수 있다.
타입 체킹을 했으므로 그럴 일은 일어날 수 없다 생각할 수 있겠지만 네트워크 호출로부터 받아온 값으로 함수를 실행하는 경우 데이터가 문자열일 수 있다.
타입스크립트에서는 런타임 타입과 선언된 타입이 맞지 않을 수 있습니다.

✅타입스크립트 타입으로는 함수를 오버로드 할 수 없다.

ts는 타입과 런타임의 동작이 무관하기 때문에 함수 오버로딩은 불가능하다.

function add(a: number, b: number): number;
function add(a: string, b: string): string;

function add(a, b) {
	return a + b;
}

ts가 함수 오버로딩 기능을 지원하기는 하지만, 온전히 타입 수준에서만 동작한다
위 코드에서는 add에 대한 처음 두 개의 선언문은 타입 정보를 제공할 뿐 이 두선언문은 타입스크립트가 자바스크립트로 변환되면서 제거되며, 구현체만 남게 된다.

✅타입스크립트 타입은 런타임 성능에 영향을 주지 않는다.

  • 타입과 타입 연산자는 자바스크립트 변환 시점에 제거되기 때문에 런타임의 성능에 아무런 영향을 주지 않는다.

  • 타입스크립트의 정적 타입은 실제로 비용이 전혀 들지 않는다.

다만, 빌드타임 오버헤드는 있다.

-추가자료-
https://velog.io/@wndud0647/TIL-25-TypeScript-%ED%83%80%EC%9E%85-%EC%84%A0%EC%96%B8-%EB%B0%8F-%EC%A2%85%EB%A5%98

https://joshua1988.github.io/ts/guide/basic-types.html#any

0개의 댓글

관련 채용 정보