interface Add {
(x:number, y:number): number
}
type Add () => number;
interface Minus {}
Array<string>
const f:true = true
function add(x:numer, y: number): number;
//js에서는 위에 사라짐
function add(x,y){
return x+y
}
같은 함수 add가 중복으로 쓰이면 원래 안되지만 타입만 나오고 아래는 선언되어 있는 케이스 존재함
let aa =123;
aa = 'hello' as unknown as number;
//js에서는 as도 사라짐
number을 as를 사용해서 억지로 unknown 타입으로 바꿔줌
never타입은 empty타입과 같음
집합에 어떤 값도 없기에 any타입을 포함하여 어떤 값도 가질 수 없다.
그래서 never타입은 점유할 수 없는, 바닥타입이라고 불린다
declare const any: any
const never: never = any // ❌ 'any' 타입은 'never'타입에 할당할 수 없다.
바닥타입이다. 바닥타입이란 ts계층 트리에서 가장 아래에 위치하여 어떤 값도 가질 수 없음을 의미
빈 배열은 never이기에 꼭 타입을 지정해줘야한다
const arr:string[] = []
허용할 수 없는 함수 매개변수에 제한을 가한다
function unknownColor(x: never): never {
throw new Error("unknown color");
}
type Color = 'red' | 'green' | 'blue';
function getColorName(c: Color): string {
switch(c) {
case 'red':
return 'is red';
case 'green':
return 'is green';
default:
return unknownColor(c); // 에러 없이 동작
}
}
const head =
document.querySelector('#head')!
head가 바뀔 수 있음
!는 js에서 사라짐
그러나 비추, 절대적일 수 없다
대신 아래처럼 써라
const head =
document.querySelector('#head')
if(head){
head.innerHTML = 'hello';
}
type World = 'world';
const a:World = 'world'; //자동완성됨
const b = `hello ${a}`;
//type Greetin = "hello world"가 됨
type Greeting = `hello ${World}`;
//현실적으로 쓸 때
type World = "world" |"around"
type Greeting = `hello ${World}`
const c: Greeting = `hello ...`
//여기서 hello world나 hello around로 타입 추천이 됨
function rest(a,...args: string[]){
console.log(a, args); //1, [2,3]
}
rest('1','2','3')
const tuple:[string, number] = ['1',1];
tuple[2]=2 ; //하면 에러, 3번째 자리에 고정적인 값이 없기에
tuple.push('hello') //대신 이거는 됨
const enum E{
Up = 3,
Down = 4,
Left = 6,
Right = 'hello',
} // 위 식은 js에서 사라짐
const a = E.Up; //a=3 나옴
const b = E.Right //b=5 나옴
//enum이 아닌 객체 형식
const E = {
Up : 0,
Down : 1,
Left : 2,
Right : 3,
} as const
//위 식은 as 뒷부분부터 js에서 사라짐
//js에 없애고 싶으면 enum 남기게 하고 싶다면 객체형식으로 쓰기
// 남길지 안남길지 모르겠다면 남기는 것 추천
// ts가 은근 모자람, 객체 형식에 숫자를 지정해서 넣었는데
// 타입추론을 정확한 숫자가 아닌 number로 받음, 추론을 못하면 내가 직접 타입을 줘야한다
const E:{Up : 0, Down : 1, Left : 2, Right : 3,} = {
Up : 0,
Down : 1,
Left : 2,
Right : 3,
}
//이렇게 쓸 수도 있지만,위에 써놓은 것처럼 as const로 상수로 지정하면 됨
//상수로 지정하면 아래 사진처럼 readonly로 나옴
const obj = {a:'123', b:'hello', c:'world'};
type Key = keyof typeof obj;
//js값은 타입으로 쓸 수가 없음
//키들만 뽑아내고 싶다면
//Key는 "a"|"b"|"c"로 나옴
type Key = typeof obj[keyof typeof obj;
//value의 타입만 뽑아내고 싶다면,
//Key는 string|string|string
또는
func add(x:string|number, y: string|number):string|number {return x+y}
add(1,2);
add('1','2');
add(1,'2');
//문제 생김
const result: string|number = add(1,2);
//add(1,2)일때 결과는 number이지만 result는 string|number로 보이게 된다.
result.charAt();//charAt는 문자열에 사용되기에 타입에러가 생김
//add처음 타입을 잘 잡아야한다.
//맞는 말인 것 같아도 줄줄이 타입에러날 수 있음
type A = string & number // 안됨
type A = {hello: 'world'} &{zero:'cho'};
const a:A = {hello:'world', zero:'cho'};
const a:A = {hello:'world'};//타입에러
//& 둘다 만족되어야함
//모든 속성이 다 있어야한다
type A = {hello: 'world'} | {zero:'cho'};//이것도 가능
const a:A = {hello:'world', zero:'cho'};
//| (유니언) 하나만 있어도 된다
확장의 개념으로 쓸 수 있음
type Animal = {breath: true};
type Mammals = Animal & {breed:true};
type Human = Mammals & {think: true};
const zero:Human = {breath: true, breed:true, think:true};
//3개 다 되어야함
중복으로 써도 됨
확장이 쉬워짐(추가)
좁은 타입에서 넓은 타입으로 대입은 가능
type A = stirng|number; //큰 타입
type B = string; //작은 타입
type C = string&number //없는 타입이지만 여기서 제일 작은 타입임
type A = {name: string};
type B = {age: string};
type C = {name: string, age:string}; //구체적일수록 좁은 타입임 === A & B
type AB = A|B //제일 넓은 타입
const c : C = {name : 'zerocho', age: 29}
const ab : AB = c;
//작은 타입에서 넓은 타입으로 넣을 수 있음
type C = {name: string, age:string};
type AB = A|B
const ab:AB = {name:'zero'};
const c: C = {name:'zero', age:29, married:false};
//C타입보다 {name:'zero', age:29, married:false}가 더 좁은데
//좁은 타입을 넓은 타입에 넣었는데 에러가 뜸
//객체 리터럴 검사라는 것 떄문에 에러 (잉여속성 검사라는 것때문에 에러가 생김)
const obj = {name:'zero', age:29, married:false}; //이렇게 변수를 빼주면 에러 사라짐
const c: C = obj;
객체 리터럴을 바로 대입해서 쓸 때 잉여속성검사가 들어간다
const c :C = {name:'zero', age:29, married:false}; //에러
const obj = {name:'zero', age:29, married:false}; //이렇게 변수를 빼주면 에러 사라짐
const c: C = obj;
return 값이 void(여기에만 값을 넣지못함) === 함수가 어떤 값을 반환하지 않겠다
function a():void {
return 3;
}
//void함수는 return값을 넣으면 안되는 타입
//대신 undefined는 됨
//null은 안됨
function a():void {
return
}
매개변수가 void 함수=== return 값을 사용하지 않겠다 ===실제 return값이 뭐든 상관하지 않겠다
function a(callback: ()=>void) {
}
a(()=> {
return '3';
});
//이렇게는 가능
method로 선언할때 void (아래와 같을때는 가능)=== return 값을 사용하지 않겠다
interface Humna {
talk: ()=>void;
}
const human:Human {
talk() {return 'abc';}
}
declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;
// declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
forEach([1, 2, 3], el => {target.push(el)});
forEach([1, 2, 3], el => target.push(el));
interface A {
talk: () => void;
}
const a: A = {
talk() { return 3; }
}
const b = a.talk(); //예상으로는 3이 나와야 하지만 Js에서 결과를 무시해버림
const b = a.talk() as unkown as number //내가 강제로 바꿀 수 있음
쉽게 말해, void
반환 타입은 함수나 메서드가 어떠한 값을 반환하지 않음을 명시적으로 나타내는 것이며, 이것은 코드를 읽는 사람에게 함수의 동작을 더 명확하게 전달하고, TypeScript가 타입 관련 오류를 잡아내도록 도와줍니다.
type B = { type: 'b', bbb: string };
type C = { type: 'c', ccc: string };
type D = { type: 'd', ddd: string };
type A = B | C | D;
function typeCheck(a: A) {
if (a.type === 'b') {
a.bbb;
} else if (a.type === 'c') {
a.ccc;
} else {
a.ddd;
}
}
//속성으로 구분하는 법
function typeCheck(a: B|C|D) {
if ('bbb' in a) { //bbb가 있는 a를 찾으면 a:B로 타입 추론됨
a.bbb;
} else if (a.type === 'c') {
a.ccc;
} else {
a.ddd;
}
}
타입을 구분해주는 커스텀함수를 우리가 직접 만들 수 있음
return 타입에 is가 들어있는 애들은 커스텀 타입가드 함수임
interface Cat { meow: number }
interface Dog { bow: number }
function catOrDog(a: Cat | Dog): a is Dog {
if ((a as Cat).meow) { return false }
return true;
}
const cat: Cat | Dog = { meow: 3 }
if (catOrDog(cat)) { //if문 안에 써야 정확한 타입이 뭔지
console.log(cat.meow);
}
if ('meow' in cat) {
console.log(cat.meow);
}
const z : unknown = 'hi';
if(z){ //true 타입이기에
z //{}타입으로 받아들임
} else {
z;
}
type A = {a:string, b: string ...}
//모든 속성이 다 문자열이길 바랄떄
type A = { [key:string] : string }
//어떤 키든 상관없이 string
//key를 줄여놓을때
type B = 'Human' | 'Mammal' | 'Animal'; //제한 걸 수 있음
type A = { [key in B] : number }
const aa : A = {Human:123, Mammal:123}
타입은 나중에 정할래, 타입을 변수처럼 정하는 것
function add<T>(x:T, y:T):T {
return x+y;
}
add(1,2); //3
add('1','2');//'12'
add(true, false) // 이것도 됨 이걸 제한하고 싶다면?
//function add<T extends number|string >(x:T, y:T):T {
return x+y;
}
extends로 제한한다
//제네릭은 선언할 때말고 사용할때 타입이 정해짐
// <T extends abstract new (...args: any) => any> // 생성자 타입,
//제한 거는 것에 제한이 없게 하고 싶으면 any로 사용
리액트 설정시
const add = <T>(x:T, y:T) => ({x,y})
//<T>하면 태그로 인식해서 에러뜰 수도 있으니 <T: unknown>
객체 타입 지정시
const a = (b: {children: string} = {children : 'zero'} ) => {}
//위와 같이 써야함