잉여 속성 검사 (해깔릴 수 있는 부분)
A 인터페이스에서는 a 프로퍼티밖에없어서 obj1에 할당하는 값에 b프로퍼티가 들어있으면 에러가발생한다.
그런데, 밑 사진처럼 obj라는 변수에 담아서 다시 할당하면 문제가 발생하지 않는다.
즉, 옵셔널로 프로퍼티가 들어가는 거라면 이런식으로 객체에 담아서 할당하면된다.
void return 타입에 Null은 불가능, undefined는 가능
void 논란
함수를 정의하는 타입은 3가지가 조금씩 다르다
- function에서 return void
실제 리턴값이 없다는 의미(void)
- 객체의 프로퍼티에서 ()=>void
리턴값을 사용하지 않겠다는 의미 (void이든 string, number.. 다상관없음, 있다해도 안쓴다는 의미여서 에러표시 x)
- 매개변수의 callback ()=>void
리턴값을 사용하지 않겠다는 의미 (void이든 string, number.. 다상관없음, 있다해도 안쓴다는 의미여서 에러표시 x)
void vs undefined
매개변수나, 메서드의 리턴값 정의에서 (그냥 function은 리턴값이 없어야함을 의미하는게 맞음)
위에서 정의했듯이 void는 리턴값을 사용하지 않는다는 의미라서 어떤 리턴값도 수용하고
undefined은 정확히 undefined이라는 return 값을 낸다라는 의미이다.
실전 예시
declare function forEach (arr:number[], callback:(el:number) => void):void;
let bank = [];
forEach([1,2,3], (el)=> {bank.push(el)});
forEach([1,2,3], (el)=> bank.push(el));
위 두개의 함수실해은 정상적으로 동작한다.
첫번째는 return 값없으니 void이고
두번째는 push의 리턴값은 지금의 경우에 number이다.
콜백, 메서드의 void의 의미는 리턴값을 사용하지 않겠다는 의미이기 때문에 오류가 발생하지 않는것이다.
declare function forEach (arr:number[], callback:(el:number) => undefined):void;
let bank = [];
forEach([1,2,3], (el)=> {bank.push(el)});
forEach([1,2,3], (el)=> bank.push(el));
하지만 위와같이 undefined로 변경해주면 둘다 에러가난다.
왜냐하면 당연스럽게도 undefined를 둘다 리턴하지 않기 때문이다.
주의해야할 점
위처럼 A는 메서드로서 void를 리턴하고 있기 때문에 -> 리턴값을 사용하지 않겠다 라는 의미이다.
그런데 a 변수에 talk에서 3을리턴하고있다.
이렇게된다면 b는 return 타입이 number 일까, void일까?
정답은 void가 되버린다. 3을 리턴함에도 불구하고..
그러니 void를 정의했다면 Return 값을 사용해선 안된다.
해결방법 (return 값 수동으로 변경하기)
아래가 위에서 설명한 경우이다. 지금 3을 리턴받아야되는데 타입은 void 이다
interface T {
talk:()=> void;
}
const a:T = {
talk(){
return 3;
}
}
const b = a.talk();
as 어썰션
그러면 as 로 강제해주면안될까? 하지만 바로변환할 수 없다.
린트에서 unknown으로 변경후 하라고한다.
const b = a.talk() as unknown as number;
이렇게하면 된다.
declare
외부에서 만들어진 변수,함수,객체들의 타입이 없을때, 직접 만들어야할 때 사용한다.
아래처럼, 우리가 외부 라이브러리에 forEach라는 함수를 가져다 사용하려고하는데, 라이브러리 설치는 했지만, type선언이 없다고 가정해보면, 우리는 계속 타입에러가 날것이다. 그럴때, declare 키워드로 선언을 해주는 것이다.
함수를 구현부 없이 선언하면 에러가난다,
하지만 바로밑에이어서 구현해주면 에러는 안난다.
이때 타입만 존재하도록하기 위해서는 declare를 붙여주면된다.(JS로 변환되면서 사라짐)
any vs unknown
any를 쓸빠엔 unknown을 써라!
예시를 들면 m은 지금 talk를 가지고있다.
그래서 없는 속성을 호출하면 에러가 나지만,
any는 타입추론을 포기하기 때문에, 에러가나지 않는다.
unknown은 할수없다 라는 에러가아니라, 뭔지 모르겠다 라는 에러이다.
그래서 사용할때 어떤 타입인지 정의해주고 사용해야한다.
try catch의 unknown 사례
대표적으로 try catch에서의 error가 unknown이다.
어떤에러가 나올지 모르기 때문에, as 키워드로 추론을 하고 사용한다.
원시값 확인하기 typeof
하단의 boolean은 a가 never로 추론된다.
never는 any와 마찬가지로 지양해야한다.
배열 확인하기 Array.isArray()
function mm(a:number | number[]){
if(Array.isArray(a)){
a.sort();
}else{
a.toFixed();
}
}
Class는 자체로 type이 된다.
클래스는 instanceof 로 확인한다.
class A {
a(){}
}
class B {
b(){}
}
function aOrB(instance:A | B){
if(instance instanceof A){
instance.a();
}else{
instance.b();
}
}
aOrB(new A());
aOrB(A); // Error
객체 타입 추론하기
내부의 프로퍼티를 비교하여 구분할수있는데, 아래처럼 c라는 것이 고유한 값이 아니게 되면 문제가된다.
그래서 총 두가지 방법이있다.
1. 값으로 구분하기
2. 속성(프로퍼티)로 구분하기
in 연산자로 객체내의 프로퍼티가 있는지 확인한다.
in연산자는 js문법이다.
const a = {
name:'kon'
}
console.log('name' in a) // true
그래서 객체를 생성할때 아래와같이 type을 구분할 수 있는 속성을 추가해주는 습관을 들이면 좋다.
이경우가 아니라면 아래처럼 in 키워드로 프로퍼티를 검사한다.
Custom type Guard
return 값에 is 키워드를 활용해서 커스텀한 타입가드를 만들어서 사용해도된다.
Promise
프로미스 실행시 상태변화
Promise -> Pending -> Settled(Resolved, Rejected)
promise 커스텀 타입가드 예시
interface 의 readonly
readonly속성을 부여하면 수정할 수 없다.
interface A {
readonly name:string;
age:number;
}
const a:A = {
name:'kong',
age:25
}
a.name = 'ha'; // error
indexed signature 어떤 키든지 받기
type A = {[key: string] : number};
const a:A = {name:11,age:323}
mapped type 다른 타입을 프로퍼티로 사용하기
type B = 'Human' | 'Mammal' | 'Animal';
type A = {[key in B]:string}
const a:A = {
}
interface , implements, private, protected
js에는 없는데, OOP에는 있는 기능들을 추가했다.
private : 자기 instance 만 사용가능
protected : 상속받아도 사용가능
interface : 추상
class : 구현
보통은 굳이 interface, implements 사용하지 않고, private, readonly 사용해서 구현함
* abstract class를 상속한 class는 abstract 메서드를 반드시 구현해주어야함.
Generic
타입을 변수처럼 사용한다
extends 키워드는 제네릭의 타입으로 들어올수 있는 것들을 제한한다.
function add<T extends number, K extends string>(a:T,b:K):T{
return a+b;
}
add(1,'2');
제네릭타입은 항상 이름뒤에 위치한다.
function add<T>(){}
class A<T>{}
interface B<T>{}
실행할때 꺽새를 통해서 타입을 명시해줄 수 있다(자동으로 추론을 잘 못할 경우)
function add<T>(a:T,b:T):T{
return a+b;
}
add<number>(1,2);
'Archive' 카테고리의 다른 글
TS 냐금냐금 - 3 (0) | 2022.07.29 |
---|---|
멋쟁이 사자처럼 해커톤을 마치며 (0) | 2022.07.28 |
TS 냐금냐금 - 1 (0) | 2022.07.25 |
CRA없이 React Typescript 환경세팅하기 [2] - webpack-dev-server (0) | 2022.07.18 |
CRA없이 React Typescript 환경세팅하기 [1] (0) | 2022.07.18 |