ts-all-in-one
- typescript ๊ณต์๋ฌธ์
- typescript ํ๋ ์ด๊ทธ๋ผ์ด๋
- typescript ํธ๋๋ถ ํ๋
- typescript ๋ฒ์ ์์ ๋ด์ญ
์ค์ตํ ์๋ฃ ๋งํฌ(์์ค ์ฝ๋ ๋ฒ์ ์ ๋ฐ๋ผ ๋ณ๋ ๊ฐ๋ฅ)
์ ์ด์ ts์ธ redux, ํจํค์ง ๋ด๋ถ์์ d.ts๋ฅผ ์ ๊ณตํ๋ axios, @types ํจํค์ง๊ฐ ๋ณ๋๋ก ์กด์ฌํ๋ react, node, express, jquery๋ก ๊ตฌ๋ถ๋จ. @types๋ DefinitelyTyped๋ผ๋ ํ๋ก์ ํธ๋ก, ์ปค๋ฎค๋ํฐ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ดํ์ ์ ๊ณตํ๋ ๊ฒ.
๊ธฐ๋ณธ ์ง์
- ๋ฉ์ธ ๋ฃฐ: typescript๋ ์ต์ข ์ ์ผ๋ก javascript๋ก ๋ณํ๋๋ค. ์์ ํ typescript ์ฝ๋๋ฅผ ๋๋ฆด ์ ์๋ ๊ฒ์ deno์ด๋ ๋์คํ๋์ง๊ฐ ์์์. ๋ธ๋ผ์ฐ์ , ๋ ธ๋๋ ๋ชจ๋ js ํ์ผ์ ์คํํ๋ค.
- typescript๋ ์ธ์ด์ด์ ์ปดํ์ผ๋ฌ(tsc)์ด๋ค. ์ปดํ์ผ๋ฌ๋ ts ์ฝ๋๋ฅผ js๋ก ๋ฐ๊ฟ์ค๋ค.
- tsc๋ tsconfig.json(tsc --init ์ ์์ฑ)์ ๋ฐ๋ผ ts ์ฝ๋๋ฅผ js(tsc ์ ์์ฑ)๋ก ๋ฐ๊ฟ์ค๋ค. ์ธํ์ธ ts์ ์์ํ์ธ js ๋ชจ๋์ ์ํฅ์ ๋ผ์น๋ฏ๋ก tsconfig.json ์ค์ ์ ๋ฐ๋์ ๋ด์ผํ๋ค.
- ๋จ์ํ ํ์ ๊ฒ์ฌ๋ง ํ๊ณ ์ถ๋ค๋ฉด tsc --noEmit ํ๋ฉด ๋๋ค.
- ๊ฐ์ธ ์๊ฒฌ: tsconfig.json์์ ๊ทธ๋ฅ esModuleInterop: true, strict: true ๋ ๊ฐ๋ง ์ฃผ๋ก ์ผ๋๋ ํธ. strict: true๊ฐ ํต์ฌ์.
- ts ํ์ผ์ ์คํํ๋ ๊ฒ ์๋๋ผ ๊ฒฐ๊ณผ๋ฌผ์ธ js๋ฅผ ์คํํด์ผ ํ๋ค.
- ์๋ํฐ๊ฐ ํ์๊ฐ ๋จ. VS Code๋ ์น์คํฐ ๋ฐ๋์ ํ์. ๋ฉ๋ชจ์ฅ์ผ๋ก ์ฝ๋ฉ ๋ถ๊ฐ๋ฅํ ์ง๊ฒฝ์ ์ด๋ฆ.
ts ๋ฌธ๋ฒ
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ์, ์์ฑ, ๋งค๊ฐ๋ณ์, ๋ฆฌํด๊ฐ์ ํ์ ์ด ๋ถ์๋ค๊ณ ์๊ฐํ๋ฉด ๋จ.
const a: number = 5;
function add(x: number, y: number): number { return x + y }
const add: (x: number, y: number) => number = (x, y) => x + y;
const obj: { lat: number, lon: number } = { lat: 37.5, lon: 127.5 };
- ํน์ํ ํ์ {} (null๊ณผ undefined๊ฐ ์๋ ๋ชจ๋ ํ์ )
const z: {} = 5;
- ts๊ฐ ์ถ๋ก ํด์ฃผ๋ ํ์ ์ด ์๋๋ฐ ์ด๋ฐ ๊ฑด ๊ทธ๋ฅ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด ๋จ. ts๊ฐ ์ถ๋ก ํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ์๋ง ์ง์ ํ์ดํํ ๊ฒ.
const a = 5;
const b = '3';
const c = a + b;
function add(x: number, y: number) { return x + y }
- : ๋ท๋ถ๋ถ, as ๋ท๋ถ๋ถ, <> ๋ถ๋ถ, interface, type, function ์ผ๋ถ๋ฅผ ์ ์ธํ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ์ ๋์ผ. ์ ์ธํ๊ณ ์๊ฐํ๋ ์ฐ์ต์ ์ด๋ฐ์ ํด์ผ ํจ.
const obj: { lat: number, lon: number } = { lat: 37.5, lon: 127.5 };
const obj = { lat: 37.5, lon: 127.5 };
const a = document.querySelector('#root') as HTMLDivElement;
const a = document.querySelector('#root');
function add<T>(x: T, y: T): T { return x + y }
function add(x, y) { return x + y }
interface A {};
type A = {};
- ์๋ฐ์คํฌ๋ฆฝํธ์ ๋นํด์ ์์ ๋๊ฐ ํ ์ค์ด๋ฆ(ex: ๋ณ์์ ๋ฌธ์์ด์ ๋ฃ์๋ค๊ฐ ์ซ์๋ก ๋ฐ๊พธ๋ ๋ฑ์ ํ๋ ์ด๋ ค์์ง)
let x = 5;
x = 'hello';
- any๋ฅผ ์ต๋ํ ์ฐ์ง ์๋ ๊ฒ์ ๋ชฉํ๋ก ํ ๊ฒ.
- never, unknown, any ํ์ ์ฃผ์ํ๊ธฐ. any๋ ์ต๋ํ ํผํ๊ณ ์ฐ๋๋ผ๋ ๋์ค์ ๊ผญ ์ ๋๋ก ํ์ดํํ๊ธฐ. never ์ข์ ์ค๋ช ๊ธ
try {
const array = []; // noImplicitAny๊ฐ false์ผ ๋
array[0];
} catch(error) {
error;
}
- ์ต๋ํ ! ๋์ if๋ฅผ ์ธ ๊ฒ
const head = document.querySelector('#head')!;
console.log(head);
const head = document.querySelector('#head');
if (head) {
console.log(head);
}
- string๊ณผ String์ ๋ค๋ฆ. ์๋ฌธ์๋ก ํ๋ ๊ฒ ๊ธฐ์ตํ๊ธฐ.
const a: string = 'hello';
const b: String = 'hell';
- ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด ํ์ ์ด ์กด์ฌ(์ ๋์ธ ๋ฑ ์ฌ์ฉ ๊ฐ๋ฅ)
type World = "world" | "hell";
// type Greeting = "hello world"
type Greeting = `hello ${World}`;
- ๋ฐฐ์ด, ํํ ๋ฌธ๋ฒ
let arr: string[] = [];
let arr2: Array<string> = [];
function rest(...args: string[]) {}
const tuple: [string, number] = ['1', 1];
tuple[2] = 'hello';
tuple.push('hello');
- enum, keyof, typeof
const enum EDirection {
Up,
Down,
Left,
Right,
}
const ODirection = {
Up: 0,
Down: 1,
Left: 2,
Right: 3,
} as const;
EDirection.Up;
(enum member) EDirection.Up = 0
ODirection.Up;
(property) Up: 0
// Using the enum as a parameter
function walk(dir: EDirection) {}
// It requires an extra line to pull out the keys
type Direction = typeof ODirection[keyof typeof ODirection];
function run(dir: Direction) {}
walk(EDirection.Left);
run(ODirection.Right);
- ๊ฐ์ฒด ํ์ดํ: type๊ณผ interface ๊ตฌ๋ถํ๊ธฐ
type A = { a: string };
const a: A = { a: 'hello' };
interface B { a: string }
const b: B = { a: 'hello' };
- union, intersection
function add(x: string | number, y: string | number): string | number { return x + y }
add(1, 2)
add('1', '2')
add(1, '2')
type A = {
a: string;
}
type B = {
b: string;
}
const aa: A | B = { a: 'hello', b: 'world' };
const bb: A & B = { a: 'hello', b: 'world' };
- interface๋ผ๋ฆฌ๋ ์๋ก ํฉ์ณ์ง.
interface A { a: string }
interface A { b: string }
const obj1: A = { a: 'hello', b: 'world' }
type B = { a: string }
type B = { b: string }
const obj2: B = { a: 'hello', b: 'world' }
- ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์์ฌ ์์ฑ ๊ฒ์ฌ๊ฐ ์์.
type A = { hello: string };
const a: A = { hello: 'world', why: 'error' };
const b = { hello: 'world', why: 'error' };
const c: A = b;
- void ํ์ ์ return๊ฐ์ ์ฌ์ฉํ์ง ์ ๊ฒ ๋ค๋ ๋ป(๋ฉ์๋๋ ๋งค๊ฐ๋ณ์์์๋ ๋ฆฌํด๊ฐ ์ฌ์ฉ ๊ฐ๋ฅ, but ์กฐ์ฌํด์ผ ํจ)
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));
interface A {
talk: () => void;
}
const a: A = {
talk() { return 3; }
}
- ํ์ ๋ง ์ ์ธํ๊ณ ์ถ์ ๋ declare(๊ตฌํ์ ๋ค๋ฅธ ํ์ผ์ ์์ด์ผ ํจ)
declare const a: string;
declare function a(x: number): number;
declare class A {}
// ์ถํ declare module, declare global, declare namespace๋ ๋ฐฐ์
function numOrStr(a: number | string) {
if (typeof a === 'string') {
a.split(',');
} else {
a.toFixed(1);
}
}
function numOrNumArr(a: number | number[]) {
if (Array.isArray(a)) {
a.slice(1);
} else {
a.toFixed(1);
}
}
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;
}
}
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)) {
console.log(cat.meow);
}
if ('meow' in cat) {
console.log(cat.meow);
}
const isRejected = (input: PromiseSettledResult<unknown>): input is PromiseRejectedResult => input.status === 'rejected';
const isFulfilled = <T>(input: PromiseSettledResult<T>): input is PromiseFulfilledResult<T> => input.status === 'fulfilled';
const promises = await Promise.allSettled([Promise.resolve('a'), Promise.resolve('b')]);
const errors = promises.filter(isRejected);
class์ธ ๊ฒฝ์ฐ instanceof ์ฐ์ฐ์๋ ๊ฐ๋ฅ!
- readonly
interface A {
readonly a: string;
b: string;
}
- class์ private, protected ์ถ๊ฐ๋จ
class B implements A {
private a: string;
protected b: string;
}
class C extends B {}
new C().a;
new C().b;
- abstract class, abstract method
abstract class X {
abstract work(user: User): boolean;
}
class Y extends X {
work(user: User): boolean {
return true;
}
}
- abstract class, abstract ์์ฑ์
const constructor: abstract new (...args: any) => any = ...
- class vs interface
๋ฐํ์์์ ์๋ ์๋.
- optional
function abc(a: number, b?: number, c: number?) {}
abc(1)
abc(1, 2)
abc(1, 2, 3)
let obj: { a: string, b?: string } = { a: 'hello', b: 'world' }
obj = { a: 'hello' };
- ์ ๋ค๋ฆญ์ ํ์ ์ ๋ํ ํจ์๋ผ๊ณ ์๊ฐํ๋ฉด ๋จ. ์ถ๋ก ์ ํ์ฉํ๊ธฐ
function add<T>(x: T, y: T): T { return x + y }
add<number>(1, 2);
add(1, 2);
add<string>('1', '2');
add('1', '2');
add(1, '2');
- ์ ๋ค๋ฆญ ์ ์ธ ์์น ๊ธฐ์ตํ๊ธฐ
function a<T>() {}
class B<T>() {}
interface C<T> {}
type D<T> = {};
const e = <T>() => {};
- ์ ๋ค๋ฆญ ๊ธฐ๋ณธ๊ฐ, extends
function add<T extends string>(x: T, y: T): T { return x + y }
add(1, 2);
add('1', '2')
// <T extends {...}> // ํน์ ๊ฐ์ฒด
// <T extends any[]> // ๋ชจ๋ ๋ฐฐ์ด
// <T extends (...args: any) => any> // ๋ชจ๋ ํจ์
// <T extends abstract new (...args: any) => any> // ์์ฑ์ ํ์
// <T extends keyof any> // string | number | symbol
- ํจ์์์ ๊ณต๋ณ์ฑ๊ณผ ๋ฐ๊ณต๋ณ์ฑ ์ฃผ์!
function a(x: string): number {
return 0;
}
type B = (x: string) => number | string;
let b: B = a;
function a(x: string): number | string {
return 0;
}
type B = (x: string) => number;
let b: B = a;
function a(x: string | number): number {
return 0;
}
type B = (x: string) => number;
let b: B = a;
function a(x: string): number {
return 0;
}
type B = (x: string | number) => number;
let b: B = a;
- ํจ์ ์ค๋ฒ๋ก๋ฉ
function add(x: number, y: number): number
function add(x: string, y: string): string
function add(x: any, y: any) {
return x + y;
}
interface Add {
(x: number, y: number): number;
(x: string, y: string): string;
}
const add: Add = (x: any, y: any) => x + y;
- infer๋ ํ์ ๋ด์์ ์ถ๋ก ๋ ๊ฐ์ผ๋ก ๋ค์ ์๋ก์ด ํ์ ์ ๋ง๋๋ ๊ฒ(๋ฐ์ utility types ์ฐธ๊ณ ).
- ํ์ ์คํฌ๋ฆฝํธ๋ ๊ฑด๋ง์ฆ์ด ์ฌํ๋ค
try {
await axios.get();
} catch (err) {
console.error(err.response?.data);
}
- this ํ์ดํ
function (this: Window, a: number, b: number) {
console.log(this);
}
utility types๋ก ์์๋ณด๊ธฐ
- Partial
type Partial<T> = {
[P in keyof T]?: T[P];
};
- Required
type Required<T> = {
[P in keyof T]-?: T[P];
};
- ReadOnly
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
- Pick
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
- Record
type Record<K extends keyof any, T> = {
[P in K]: T;
};
- Exclude
type Exclude<T, U> = T extends U ? never : T;
- Extract
type Extract<T, U> = T extends U ? T : never;
- Omit
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
- NonNullable
type NonNullable<T> = T extends null | undefined ? never : T;
- Parameters
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
- ConstructorParameters
type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
- ReturnType
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
- InstanceType
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
- ๊ธฐํ
/**
* Convert string literal type to uppercase
*/
type Uppercase<S extends string> = intrinsic;
/**
* Convert string literal type to lowercase
*/
type Lowercase<S extends string> = intrinsic;
/**
* Convert first character of string literal type to uppercase
*/
type Capitalize<S extends string> = intrinsic;
/**
* Convert first character of string literal type to lowercase
*/
type Uncapitalize<S extends string> = intrinsic;
function applyStringMapping(symbol: Symbol, str: string) {
switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {
case IntrinsicTypeKind.Uppercase: return str.toUpperCase();
case IntrinsicTypeKind.Lowercase: return str.toLowerCase();
case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1);
case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1);
}
return str;
}
/**
* Marker for contextual 'this' type
*/
interface ThisType<T> { }
ts ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์
- package.json์ types ์์ฑ์ ์ ํ ํ์ผ์ด ๋ฉ์ธ ํ์ดํ ํ์ผ์.
- npmjs.com์์ ํจํค์ง๋ฅผ ๊ฒ์ํ์ ๋ ํจํค์ง ์ฐ์ธก์ TS๋ก ๋จ๋ฉด ts ์ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ณ , DT๋ก ๋จ๋ฉด @types๋ฅผ ์ค์นํด์ผ ํ๋ฉฐ, ๊ทธ๊ฒ๋ง์ ๋ ์์ผ๋ฉด ์ง์ ํ์ดํํด์ผ ํจ
- ์ฒซ ๋ฒ์งธ ์ค๋ถํฐ ๋ณด๊ธฐ ๋ณด๋ค๋ ๋ง์ง๋ง ์ค exports default๋ export = ๋ถ๋ถ์ ๋ณด๊ณ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ ๊ฒ ์ข์
- ์ ๋ค๋ฆญ์ด ์ ์ผ ์ฝ๊ธฐ ์ด๋ ค์์ ์ ๋ค๋ฆญ ๋ถ๋ถ์ ๋ฐ๋ก ํ๊ธฐํ๋ฉด์ ๋ณด๋๊ฒ ์ข์
๋ชจ๋ ์์คํ
๋ชจ๋ vs ์คํฌ๋ฆฝํธ
top level import/export๊ฐ ์์ผ๋ฉด ๋ชจ๋. ์์ผ๋ฉด ์คํฌ๋ฆฝํธ ํ์ผ
- ์คํฌ๋ฆฝํธ ํ์ผ์ด๋ฉด ์ ์ญ์ ์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํจ
- ๋ค์์ export๊ฐ top level์ ์์ง ์์ผ๋ฏ๋ก ๋ชจ๋ ์๋, ์คํฌ๋ฆฝํธ ํ์ผ์
declare module "hello" {
export default class {}
}
๋ชจ๋ ์ข ๋ฅ
// commonjs
export = A // export ๋ฐฉ์
import A = require('a') // import(module = commonjs)
import * as A from 'a'; // import(module = es2015, esModuleInterop = false)
import A from 'a'; // import(module = es2015, esModuleInterop = true)
// UMD
export = A // commonjs๋ฅผ ์ํด
export as namespace A // ์คํฌ๋ฆฝํธ ํ์ผ์ ์ํด, ์คํฌ๋ฆฝํธ ํ์ผ์์๋ import ์์ด namespace๋ก ๋ถ๋ฌ์ฌ ์ ์์
// ESM, ํ์ค, ๊ถ์ฅ ๋ฐฉ์
export default A;
import A from 'a';
export * from '๋ชจ๋๋ช
' // ๋ชจ๋๋ก๋ถํฐ ๋ชจ๋ ๊ฒ์ ์ํฌํธํ ๋ค์์ ๋ค์ export, default ๋ชป ๊ฐ์ ธ์ค๊ณ commonjs ๋ชจ๋๋ ๋ชป ๊ฐ์ ธ์ด
export * as namespace from '๋ชจ๋๋ช
' // ๋ชจ๋๋ก๋ถํฐ ๋ชจ๋ ๊ฒ์ ์ํฌํธํ๋ค์์ as์ ์ ํ namespace๋๋ก export(default ๊ฐ์ ธ์ฌ ์ ์์, commonjs ๋ชจ๋ ๋ชป ๊ฐ์ ธ์ด)
import { namespace } from '๋ชจ๋๋ช
'; namespace.default; // ์ด ๋ฐฉ์์ผ๋ก default ์ ๊ทผ ๊ฐ๋ฅ
declare global, declare module
declare global๋ ๋ชจ๋์ด์ด์ผ ํด์ top level import/export ํ์
declare global {
interface Error {}
}
export {} // export๋ import ํ์
์คํฌ๋ฆฝํธ ํ์ผ์ ์ฒ์๋ถํฐ ์ ์ญ์ด๋ฏ๋ก declare global ์์ด ๊ทธ๋ฅ ์ฐ๋ฉด ๋จ
interface Error {}
declare module์ ์คํฌ๋ฆฝํธ ํ์ผ์ ํ๋ฉด ๊ธฐ์กด ํ์ ์ ์ธ ๋์ฒด, ๋ชจ๋ ํ์ผ์ ํ๋ฉด ๊ธฐ์กด ํ์ ์ ์ธ๊ณผ ๋ณํฉ๋จ.
declare module "express-session" {
interface SessionData {
sessionData: string;
}
}
export {} // ์๋ ์๋๊ฐ ๋ชจ๋/์คํฌ๋ฆฝํธ ํ์ผ์ ๊ฒฐ์ ํ๋ฏ๋ก ์ค์
jQuery์ ํ์ดํ
$( "p" ).removeClass( "myClass noClass" ).addClass( "yourClass" );
$(["p", "t"]).text("hello");
const tag = $( "ul li" ).addClass(function( index ) {
return "item-" + index;
});
$(tag).html(function (i: number) {
console.log(this);
return $(this).data('name') + '์
๋๋ค';
});
export = jQuery;
declare const jQuery: JQueryStatic;
declare const $: JQueryStatic;
interface JQueryStatic {
<TElement extends HTMLElement = HTMLElement>(html: JQuery.htmlString, ownerDocument_attributes?: Document | JQuery.PlainObject): JQuery<TElement>;
<TElement extends Element = HTMLElement>(selector: JQuery.Selector, context?: Element | Document | JQuery | JQuery.Selector): JQuery<TElement>;
}
interface JQuery<TElement = HTMLElement> extends Iterable<TElement> {
addClass(className_function: JQuery.TypeOrArray<string> | ((this: TElement, index: number, currentClassName: string) => string)): this;
removeClass(className_function?: JQuery.TypeOrArray<string> | ((this: TElement, index: number, className: string) => string)): this;
on<TType extends string>(
events: TType,
handler: JQuery.TypeEventHandler<TElement, undefined, TElement, TElement, TType> | false
): this;
}
axios์ ํ์ดํ
index.d.ts
declare const axios: AxiosStatic;
export default axios;
export interface AxiosStatic extends AxiosInstance {
create(config?: CreateAxiosDefaults): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
Axios: typeof Axios;
AxiosError: typeof AxiosError;
readonly VERSION: string;
isCancel(value: any): value is Cancel;
all<T>(values: Array<T | Promise<T>>): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;
formToJSON(form: GenericFormData|GenericHTMLFormElement): object;
}
export interface AxiosInstance extends Axios {
<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): AxiosPromise<R>;
<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): AxiosPromise<R>;
defaults: Omit<AxiosDefaults, 'headers'> & {
headers: HeadersDefaults & {
[key: string]: AxiosHeaderValue
}
};
}
export class Axios {
constructor(config?: AxiosRequestConfig);
defaults: AxiosDefaults;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
getUri(config?: AxiosRequestConfig): string;
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
get<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
delete<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
head<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
options<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>;
post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
postForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
putForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patchForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
}
export interface AxiosResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
config: AxiosRequestConfig<D>;
request?: any;
}
react์ ํ์ดํ
export = React; declare namespace React, declare global, namespace JSX
import React = require('react');
import * as React from 'react';
React.useEffect
return์ ๋ฌด์์ด ๋ค์ด๊ฐ ์ ์์๊น? JSX, string, null?
function App(): JSX.Element {
...
}
const App: FC<{}> = () => <div />;
interface Element extends React.ReactElement<any, any> { }
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
}
type JSXElementConstructor<P> =
| ((props: P) => ReactElement<any, any> | null)
| (new (props: P) => Component<any, any>);
class Component<P, S> {
render(): ReactNode;
}
interface FunctionComponent<P = {}> {
// (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null; // React17
(props: P, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
type ReactText = string | number;
type ReactChild = ReactElement | ReactText;
type ReactFragment = {} | Iterable<ReactNode>;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
interface ReactPortal extends ReactElement {
key: Key | null;
children: ReactNode;
}
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
type VFC<P = {}> = VoidFunctionComponent<P>;
interface VoidFunctionComponent<P = {}> {
(props: P, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
ํ ํ์ดํ
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
type SetStateAction<S> = S | ((prevState: S) => S);
type Dispatch<A> = (value: A) => void;
function useRef<T>(initialValue: T): MutableRefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T>;
function useRef<T = undefined>(): MutableRefObject<T | undefined>;
interface MutableRefObject<T> {
current: T;
}
interface RefObject<T> {
readonly current: T | null;
}
function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;
function useEffect(effect: EffectCallback, deps?: DependencyList): void;
type EffectCallback = () => (void | Destructor);
type DependencyList = ReadonlyArray<unknown>;
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
function useCallback<T extends Function>(callback: T, deps: DependencyList): T;
function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;
tsconfig.json "jsx": "react"๋ก
import * as React from 'react';
import { useState, useCallback, useRef } from 'react';
const WordRelay = () => {
const [word, setWord] = useState('์ ๋ก์ด');
const [value, setValue] = useState('');
const [result, setResult] = useState('');
const inputEl = useRef(null);
const onSubmitForm = useCallback((e) => {
e.preventDefault();
const input = inputEl.current;
if (word[word.length - 1] === value[0]) {
setResult('๋ฉ๋๋');
setWord(value);
setValue('');
if (input) {
input.focus();
}
} else {
setResult('๋ก');
setValue('');
if (input) {
input.focus();
}
}
}, [word, value]);
const onChange = useCallback((e) => {
setValue(e.currentTarget.value)
}, []);
return (
<>
<div>{word}</div>
<form onSubmit={onSubmitForm}>
<input
ref={inputEl}
value={value}
onChange={onChange}
/>
<button>์
๋ ฅ!</button>
</form>
<div>{result}</div>
</>
);
};
export default WordRelay;
redux์ ํ์ดํ
export interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T, ...extraArgs: any[]): T
}
export interface Action<T = any> {
type: T
}
export interface AnyAction extends Action {
// Allows any extra properties to be defined in an action.
[extraProps: string]: any
}
export interface ActionCreator<A, P extends any[] = any[]> {
(...args: P): A
}
export type Reducer<S = any, A extends Action = AnyAction> = (
state: S | undefined,
action: A
) => S
export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> {
dispatch: D
getState(): S
}
export interface Middleware<
_DispatchExt = {}, // TODO: remove unused component (breaking change)
S = any,
D extends Dispatch = Dispatch
> {
(api: MiddlewareAPI<D, S>): (
next: D
) => (action: D extends Dispatch<infer A> ? A : never) => any
}
react-redux์ ํ์ดํ
export const useSelector = /*#__PURE__*/ createSelectorHook()
export function createSelectorHook(
context = ReactReduxContext
): <TState = unknown, Selected = unknown>(
selector: (state: TState) => Selected,
equalityFn?: EqualityFn<Selected>
) => Selected {
}
export const useDispatch = /*#__PURE__*/ createDispatchHook()
export function createDispatchHook<
S = unknown,
A extends Action = AnyAction
// @ts-ignore
>(context?: Context<ReactReduxContextValue<S, A>> = ReactReduxContext) {
const useStore =
// @ts-ignore
context === ReactReduxContext ? useDefaultStore : createStoreHook(context)
return function useDispatch<
AppDispatch extends Dispatch<A> = Dispatch<A>
>(): AppDispatch {
const store = useStore()
// @ts-ignore
return store.dispatch
}
}
Provider ์์ค ๋งํฌ ํ ์์ค ๋งํฌ
Node์ ํ์ดํ
<reference path="..."์ ํด๋น ํ์ผ์ ํ์ ๋ค์ ๋๊ณ ์ค๋ ๊ฒ. ์์ฆ ํ ํ์ ์์ d.ts ํ์ผ์ declare module 'fs:promises'๋ก import 'fs:promises' ํ ๋ ์ด๋ค ํ์ ์ด ๋ ์ง ์์ฑํ ์ ์์.
function createServer(requestListener?: RequestListener): Server;
type RequestListener = (req: IncomingMessage, res: ServerResponse) => void;
function readFile(path: PathLike | number, options: { encoding?: null; flag?: string; } | undefined | null, callback: (err: NodeJS.ErrnoException | null, data: Buffer) => void): void;
function readFile(path: PathLike | FileHandle, options?: { encoding?: null, flag?: string | number } | null): Promise<Buffer>;
type PathLike = string | Buffer | URL;
function join(...paths: string[]): string;
Express์ ํ์ดํ
export = e;
declare function e(): core.Express;
declare namespace e {
var json: typeof bodyParser.json;
var urlencoded: typeof bodyParser.urlencoded;
}
interface RequestHandler<
P = core.ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = core.Query,
Locals extends Record<string, any> = Record<string, any>
> extends core.RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> {}
import * as core from 'express-serve-static-core';
ํ์ ํ์ฅ์ ์ํ ์ฅ์น
// This extracts the core definitions from express to prevent a circular dependency between express and serve-static
declare global {
namespace Express {
// These open interfaces may be extended in an application-specific manner via declaration merging.
// See for example method-override.d.ts (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/method-override/index.d.ts)
interface Request {}
interface Response {}
interface Application {}
}
}
export interface Request<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs,
Locals extends Record<string, any> = Record<string, any>
> extends http.IncomingMessage,
Express.Request {}
import { ParsedQs } from 'qs';
export {};
export type Query = ParsedQs;
export interface ParamsDictionary {
[key: string]: string;
}
export interface RequestHandler<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs,
Locals extends Record<string, any> = Record<string, any>
> {
// tslint:disable-next-line callable-types (This is extended from and can't extend from a type alias in ts<2.2)
(
req: Request<P, ResBody, ReqBody, ReqQuery, Locals>,
res: Response<ResBody, Locals>,
next: NextFunction,
): void;
}
export interface NextFunction {
(err?: any): void;
/**
* "Break-out" of a router by calling {next('router')};
* @see {https://expressjs.com/en/guide/using-middleware.html#middleware.router}
*/
(deferToNext: 'router'): void;
/**
* "Break-out" of a route by calling {next('route')};
* @see {https://expressjs.com/en/guide/using-middleware.html#middleware.application}
*/
(deferToNext: 'route'): void;
}
export interface Express extends Application {
request: Request;
response: Response;
}
export interface Application<
Locals extends Record<string, any> = Record<string, any>
> extends EventEmitter, IRouter, Express.Application {
use: ApplicationRequestHandler<this>;
}
export type ApplicationRequestHandler<T> = IRouterHandler<T> &
IRouterMatcher<T> &
((...handlers: RequestHandlerParams[]) => T);
export type RequestHandlerParams<
P = ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = ParsedQs,
Locals extends Record<string, any> = Record<string, any>
> =
| RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>
| ErrorRequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>
| Array<RequestHandler<P> | ErrorRequestHandler<P>>;
passport ํ์ดํ
declare global {
namespace Express {
// tslint:disable-next-line:no-empty-interface
interface AuthInfo {}
// tslint:disable-next-line:no-empty-interface
interface User {}
interface Request {
authInfo?: AuthInfo | undefined;
user?: User | undefined;
// These declarations are merged into express's Request type
login(user: User, done: (err: any) => void): void;
login(user: User, options: any, done: (err: any) => void): void;
logIn(user: User, done: (err: any) => void): void;
logIn(user: User, options: any, done: (err: any) => void): void;
logout(options: { keepSessionInfo?: boolean }, done: (err: any) => void): void;
logout(done: (err: any) => void): void;
logOut(options: { keepSessionInfo?: boolean }, done: (err: any) => void): void;
logOut(done: (err: any) => void): void;
isAuthenticated(): this is AuthenticatedRequest;
isUnauthenticated(): this is UnauthenticatedRequest;
}
interface AuthenticatedRequest extends Request {
user: User;
}
interface UnauthenticatedRequest extends Request {
user?: undefined;
}
}
}
passport-local ํ์ดํ
import { Strategy as PassportStrategy } from "passport-strategy";
import express = require("express");
interface IStrategyOptions {
usernameField?: string | undefined;
passwordField?: string | undefined;
session?: boolean | undefined;
passReqToCallback?: false | undefined;
}
interface IStrategyOptionsWithRequest {
usernameField?: string | undefined;
passwordField?: string | undefined;
session?: boolean | undefined;
passReqToCallback: true;
}
interface IVerifyOptions {
message: string;
}
interface VerifyFunctionWithRequest {
(
req: express.Request,
username: string,
password: string,
done: (error: any, user?: any, options?: IVerifyOptions) => void
): void;
}
interface VerifyFunction {
(
username: string,
password: string,
done: (error: any, user?: any, options?: IVerifyOptions) => void
): void;
}
declare class Strategy extends PassportStrategy {
constructor(
options: IStrategyOptionsWithRequest,
verify: VerifyFunctionWithRequest
);
constructor(options: IStrategyOptions, verify: VerifyFunction);
constructor(verify: VerifyFunction);
name: string;
}
d.ts ์ฌ์ฉํ๊ธฐ
- ๊ทธ๋ฅ ์ผ๋ฐ ts ํ์ผ์ ํ์ ์ ์ธํด๋ ๋จ
- BUT, importํ ๊ฒ๊ณผ ์ธํฐํ์ด์ค ์ด๋ฆ์ด ๊ฒน์น๋ฉด ์๋ฌ ๋ฐ์
- ์ด๋ด ๊ฒฝ์ฐ d.ts๋ก ๋ถ๋ฆฌ(d.ts๋ ํ์ ๋ง ์๊ณ ๊ตฌํ์ ์๋ ํ์ผ)
- ์ฐ์ declare global, declare module, declare namespace ์์ด ํ์ดํํ๊ธฐ
- ํ์ฅํ๊ณ ์ถ์ ์ธํฐํ์ด์ค๊ฐ ์ ๋ ๊ฒ ๋์ด์๋ค๋ฉด declare ์ถ๊ฐ
- ํ ๋ฒ declare ์ด ๋ธ๋ญ ์์์๋ ์ถ๊ฐ์ ์ผ๋ก declare ํ์ ์์
์ง์ ํ์ดํํ๊ธฐ
types/๋ชจ๋๋ช .d.ts (๊ผญ types ํด๋ ์์ ์์ ํ์๋ ์์)
declare module "๋ชจ๋๋ช
" {
// import๋ export ํ๋ ํ์
}