Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3장] 타입 추론 (아이템 19 ~ 아이템 27) #4

Open
dahye1013 opened this issue Sep 26, 2022 · 27 comments
Open

[3장] 타입 추론 (아이템 19 ~ 아이템 27) #4

dahye1013 opened this issue Sep 26, 2022 · 27 comments
Labels

Comments

@dahye1013
Copy link
Member

dahye1013 commented Sep 26, 2022

[3장 퀴즈]

타입 추론 (아이템 19 ~ 아이템 27)

아래 마크다운을 복사 붙여넣기해서 코멘트로 퀴즈를 달아주세요 :)
객관식, 주관식에 상관없이 편하게 만들어주세요!

부가 설명을 달고 싶다면, 해설을 정답과 함께 옵션으로 작성하시면 됩니다. ☺️

예시

### 아이템 N 

퀴즈 내용 객관식의 정답을 골라보세요!
(퀴즈 내용)
1. 1번 
2. 2번
3. 3번

<details>
<summary>퀴즈 정답</summary>
<div markdown="1">    
정답은 1번!
</div>
</details>
@dahye1013
Copy link
Member Author

dahye1013 commented Sep 26, 2022

아이템 21 - 타입 넓히기

타입 넓히기로 오류가 발생할때는 const 단언문을 사용해서 타입을 좁힐 수 있습니다.
어떻게 좁혀지는지 아래 예제의 타입을 추론해보세요!

const v1 = {
    x:1,
    y:2,
}

const v2 = {
    x:1 as const,
    y:2,
}

const v3 = {
    x:1,
    y:2,
} as const;
퀴즈 정답

Screen Shot 2022-09-26 at 8 48 27 PM

👇Playground 에서 확인하기!

Playground Link

@areumsheep
Copy link
Member

areumsheep commented Sep 26, 2022

아이템 22 - 타입 좁히기

🤔 여러분의 타입 좁히기 실력을 테스트해볼까요?!
(1) 부분에서 어떤 타입이 출력될까요?

console.log(typeof null); // => 'object'

const el = document.getElementById('foo'); // 타입: HTMLElement | null

if(typeof el !== 'object') {
     el; // (1) 어떤 타입이 출력될까요?
}
퀴즈 정답

image

정답은! never 입니다.
정답을 맞추셨다면 당신은 이미 타입스크립트 숙련자입니다! 👏 

@areumsheep
Copy link
Member

아이템 26 - 타입 추론에 문맥이 어떻게 사용되는지 이해하기

아래 코드는 왜 에러가 발생할까요?

function panTo(where: [number, number]) { /* ... */ }

panTo([10, 20]); // 정상

const loc = [10, 20];
panTo(loc); // 에러 발생!
퀴즈 정답

loc를 [number, number]로 추론하는 것이 아니라, number[]로 추론하기 때문입니다.

const loc: [number, number] = [10, 20]; 로 변경한다면 에러가 사라질 것입니다.

@dahye1013 dahye1013 added the 3장 label Sep 26, 2022
@tooooo1
Copy link
Contributor

tooooo1 commented Oct 1, 2022

아이템 19

interface Vector2D { x: number; y: number;}
function add(a: Vector2D , b: Vector2D) {
   return { x:a.x + b.x, y: a.y + b.y };
}

위 코드의 return 타입을 추론해보세요.

퀴즈 정답
정답은 {x: number; y: number; } 입력은 Vector2D지만 출력은 다르게 추론된다.

@tooooo1
Copy link
Contributor

tooooo1 commented Oct 1, 2022

아이템 19

eslint 규칙 중 @typescript-eslint/no-inferrable-types의 역할은?

퀴즈 정답
정답은 작성된 모든 타입 구문이 정말로 필요한지를 확인할 수 있다. 불필요한 어노테이션을 찾는데 유용하다고 생각해서 퀴즈로 냈어요!

@tooooo1
Copy link
Contributor

tooooo1 commented Oct 1, 2022

아이템 21

타입 넓히기 과정을 제어할 수 있는 방법 중에는 const가 있습니다. 그렇지만 const는 만능이 아닌데요. 어떠한 문제때문에 만능이 아닐까요?

퀴즈 정답
const는 객체와 배열의 경우에 여전히 문제가 있다. 객체의 경우, 각 요소를 let으로 할당된 것처럼 다룬다.

@sooooo-an
Copy link

아이템 19

타입스크립트는 매개변수의 최종 사용처까지 참고하여 타입을 추론한다

  1. O
  2. X
퀴즈 정답
정답은 2번! 타입스크립트에서 변수의 타입은 일반적으로 처음 등장할 때 결정된다.

@sooooo-an
Copy link

아이템 20

다음 코드에서 추후에 문제가 생길 것 같은 타입은?

// 1)
type LocalStorageKey = 'toolbar' | 'theme' | 'filter';

// 2)
type ToolbarValue = {
  chat: boolean;
  comment: boolean;
};

// 3)
type ThemeValue = 'dark' | 'light';
// 4)
type FilterValue = {
  status: string[];
  subtask: boolean;
};
// 5)
type LocalStorageValue = ToolbarValue | ThemeValue | FilterValue;
퀴즈 정답
정답은 5번! 다른 타입들이 유니온타입으로 묶여져있으면, 나중에 리턴값으로 사용하거나 객체 타입의 프로퍼티를 사용할 때, 타입 에러가 나서 사용이 어렵다.

@sooooo-an
Copy link

아이템 22

타입을 좁히는 방법이 아닌 것은?
(퀴즈 내용)

  1. 태그 사용 (태그된 유니온, 구별된 유니온)
  2. typeof document.getElementById('foo') === 'object'
  3. Array.isArray내장함수 사용
퀴즈 정답
정답은 2번! document.getElementById('foo') 의 경우, HTMLElement | null 의 타입을 갖는데, null도 object이기때문에 타입이 좁혀지지 않는다

@MINGDY98
Copy link

MINGDY98 commented Oct 2, 2022

아이템 27

type Language = 'JavaScript' | 'TypeScript'| 'Python';
interface GovernedLanguage{
  language: Language;
  oprganization: string;
}

function complain(language: GovernedLanguage){/*..*/}

complain({language: 'TypeScript', organization: 'Microsoft'});//정상

const ts = {
  language: 'TypeScript',
  organization: 'Microsoft',
}
complain(ts);
    //오류 발생

다음 코드에서 오류가 발생하는 원인이 무엇인가?

퀴즈 정답

ts객체에서 language 타입이 string으로 추론되기 때문에 발생하는 문제.
타입선언을 통해 language 타입을 제한하거나 language를 상수로 만들어 문제를 해결한다.

@MINGDY98
Copy link

MINGDY98 commented Oct 2, 2022

아이템 20

타입이 다른 값을 다룰 때에는 변수를 재사용하지 않는 것이 좋다(O/X)

퀴즈 정답
O 유니온 타입으로 코드가 동작할 수 있게 할 수는 있겠지만, 해당 변수를 사용할 때마다 어떤 타입인지 확인해야 하기 때문에 별도의 변수를 도입하는### 아이템 N

퀴즈 내용 객관식의 정답을 골라보세요!
(퀴즈 내용)

  1. 1번
  2. 2번
  3. 3번
퀴즈 정답
정답은 1번!
것이 좋다.

@MINGDY98
Copy link

MINGDY98 commented Oct 2, 2022

아이템 19

타입스크립트 코드를 작성할 때 타입 구문을 최대한 상세하게 명시하는 것이 좋은 코드 스타일이다.(O/X)

퀴즈 정답
X - 타입 추론이 된다면 명시적 타입 구문은 필요가 없다. 비생산적이며 좋지 않은 스타일로 여겨질 수 있다.

@areumsheep
Copy link
Member

아이템 19

아래 네모에 들어갈 말은?

ㅁㅁㅁㅁ ㅁㅁㅁ은 모든 지역 변수의 타입이 추론되도록 합니다.

const logPerson(person: Person) {
  const {name, nickname, IQ} = person; //위 네모를 코드 상에 이런 식으로 표현할 수 있다.
  console.log(`${name}의 별명은 ${nickname}이고 IQ는 ${IQ}이다.`);
}
퀴즈 정답

비구조화 할당문!!!
비구조화 할당문은 불필요한 타입 선언을 하지 않아 코드가 번잡해지지 않도록 도와준다.

@dahye1013
Copy link
Member Author

아이템 19

타입스크립트는 추론 가능한 타입을 사용해서 장황한 코드를 방지할 수 있습니다.
추론 되는 경우에도 타입을 명시하는 경우는 어떤 경우일까요?

퀴즈 정답
  1. 반환 타입을 명시하여 함수를 명확하게 알 수 있게 하는 경우입니다.
    (입력, 출력 타입을 명확하게 하여 함수 시그니처를 먼저 작성하여 원하는 방식으로 구현하게 하는 경우)

  2. 명명된 타입을 사용하는 경우입니다.
    (반환 타입을 명시하면 더욱 직관적인 표현이 됩니다. 추론 값이 일관적이지 않은 경우 개발자를 혼동스럽게 할 수 있습니다.)

@yeomgahui
Copy link

yeomgahui commented Oct 3, 2022

아이템 19

다음 코드를 에러가 나지 않게 변경해주세요.

const cache: {[ticker:string]: number} = {};
function getQuote(ticker:string){
    if(ticker in cache) {
        return cache[ticker]; //Error Promise 타입이 이남
    }

    return fetch(`https://quotes.example.com/?=${ticker}`)
    .then(response => response.json())
    .then(quote => {
        cache[ticker] = quote;
        return quote;
    });
}
퀴즈 정답
const cache: {[ticker:string]: number} = {}; async function getQuote(ticker:string): Promise{ if(ticker in cache) { return cache[ticker]; //Error Promise 타입이 이남 }
return fetch(`https://quotes.example.com/?=${ticker}`)
.then(response => response.json())
.then(quote => {
    cache[ticker] = quote;
    return quote;
});

}

@yeomgahui
Copy link

아이템 N

객체를 선언할때 속성을 제각각 추가하는것이 좋은 방법이다. ( O/X)

퀴즈 정답
정답은 x 객체를 한번에 선언하는것이 타입 추론에 유리하기 때문에 정답은 X입니다.

@dahye1013
Copy link
Member Author

아이템 23

null, {} 를 사용하여 안전하게 조건부 속성을 추가 할 수 있습니다.
아래 예시에서 president 객체 속성을 추론해보세요!

declare let hasMiddle: boolean;
const firstLast = { frist : 'Harry' , last : 'Trunman' };
const president = {...firstLast, ...(hasMiddle? {middle: 'S'}: {})};
퀴즈 정답
declare const president: {
    middle?: string | undefined;
    frist: string;
    last: string;
};

@yeomgahui
Copy link

아이템 22

다음 타입을 좁혀보세요!

interface Fish {
    swim: () => {}
}
interface Bird {
    fly: () => {}
}
function isFish(animal: Fish|Bird){
      return (animal as Fish).swim !== undefined
}

function doSomething(animal: Fish | Bird) {
  if (isFish(animal)) {
    animal.swim() 
  } else {
    animal.fly() 
  }
}
퀴즈 정답
interface Fish {
    swim: () => {}
}
interface Bird {
    fly: () => {}
}
function isFish(animal: Fish|Bird): animal is Fish{
      return (animal as Fish).swim !== undefined
}

function doSomething(animal: Fish | Bird) {
  if (isFish(animal)) {
    animal.swim() 
  } else {
    animal.fly()
  }
}

@seojihwan
Copy link

아이템 19

타입은 가급적 선언해서 사용하는게 좋다 O/X

퀴즈 정답 X 때에따라 다름 대부분의 경우 타입스크립트가 타입 추론을 한다. 하지만 안전하게 사용할 필요가 있는경우, 더 좁은 범위의 타입으로 추론되어야 하는 경우 등에는 선언을 사용해주는 것이 좋은 경우가 있다.

@seojihwan
Copy link

아이템 22

const a = [10, 10] // ?
추론되는 a의 타입은?

퀴즈 정답 number[] 튜플타입으로 사용할 필요가 있는경우 as const 또는, 타입 선언을 활용하자

@seojihwan
Copy link

아이템 24

다음의 타입스크립트 코드의 문제점은?

interface Person {
  nickname?: string
}

function getNickname(person: Person){
  const nickname = person.nickname

  if(nickname != null){
    return person.nickname
  }

  throw Error()
}
퀴즈 정답 별도의 식별자로 재선언하여, 타입 정적 흐름 분석을 방해함 person.nickname // string | undeinfed 로 잡힘

@jlee0505
Copy link
Member

jlee0505 commented Oct 3, 2022

아이템 21

아래 코드를 참조하여 1,2 번 문제의 결과를 추측하세요.

const v1 = {
x: 1,
y: 2,
}; 

const v2 = {
x: 1 as const,
y: 2,
};
</div>
  1. console.log(type of v1) ?
  2. console.log(type of v2) ?
퀴즈 정답
1. // Type is { x: number; y: number; } 2. // Type is { x: 1; y: number; }

@jlee0505
Copy link
Member

jlee0505 commented Oct 3, 2022

아이템 22

type narrowing 을 하는 방법에는 여러가지가 있다. 아래 코드에서 쓰인 방법으로 적절한 것은?

interface A { a: number }
interface B { b: number }
function pickAB(ab: A | B) {
 if ('a' in ab) {
 ab // Type is A
 } else {
 ab // Type is B
 }
 ab // Type is A | B
}
  1. Array.isArray() 사용
  2. conditional 사용
  3. property check 사용
  4. instanceOf 사용
  5. throwing or returning 사용
퀴즈 정답
정답은 3번!

@jlee0505
Copy link
Member

jlee0505 commented Oct 3, 2022

아이템 24

Which one would be the possibly the most correct properties that the below code infers?

function isPointInPolygon(polygon: Polygon, pt: Coordinate) {
 const {bbox} = polygon;
 if (bbox) {
 const {x, y} = bbox;
 if (pt.x < x[0] || pt.x > x[1] ||
 pt.y < x[0] || pt.y > y[1]) {
 return false;
 }
 }
 // ...
}
  1. Aliasing can prevent TypeScript from narrowing types. If you create an alias for a
    variable, use it consistently.
  2. Use destructuring syntax to encourage consistent naming.
  3. Be aware of how function calls can invalidate type refinements on properties.
    Trust refinements on local variables more than on properties.
퀴즈 정답
Answer: 2 The above code explains the effect of using destructuring syntax.

@parksil0
Copy link

아이템 22

아래의 예제 코드에서 올바른 타입은?

let number1 = 1;
const number2 = 2;
퀴즈 정답
* number1 = number
* number2 = 2

@parksil0
Copy link

아이템 26

아래의 코드에서 추론되는 타입은?

const arr = [10, 10]
퀴즈 정답
정답은 number[]이다. const로 선언하더라도 배열이라면 추가하거나 제거할 수 있기 때문에 [number, number]로 추론하지 않는다.
만약 튜플타입을 생각한다면 타입 선언을 해야하거나 as const를 붙여야한다.

@parksil0
Copy link

아이템 24

아래 코드 예제 중 주석 부분에 에러가 발생한다. 그 이유는?

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

interface WeightAndHeight {
  weight: number;
  height: number;
}

interface Person {
  required: NameAndAge;
  optional?: WeightAndHeight;
}

const seal: Person = {
  required: {
    name: 'Seal',
    age: 29,
  },
  optional: {
    weight: 178,
    height: 77,
  },
};

function getPersonInfo(person: Person) {
  const optional = person.optional;

  if (person.optional) {
    return ({ weight: optional.weight, height: optional.height }); // Object is possibly 'undefined'.ts(2532)
  }

  // ...
}
퀴즈 정답
person.optinal의 별칭인 optional은 undefined일 가능성이 있기 때문이다. 분기분 내의 person.optional은 타입이 WeightAndHeight인 반면, optional은 WeightAndHeight | undefined이다.
만약 undefined를 검사하고싶다면, 동일한 별칭을 사용해야한다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants