Set Up
touch index.ts && tsc --init
이라는 명령어를 쳐서 프로젝트를 만들어 줍니다. 그러면 tsconfig.json이라는 파일이 생성될 것이고, 아래와 같이 작성해 줍니다.
tsconfig.json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
"strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
그리고 tsc라고 명령어를 쳐주면 index.ts파일을 인식해서 아래와 같이 index.d.ts, sourcemap, js파일 3개를 만들어 주게 됩니다.
Implicit Types vs Explicit Types
let c = [];
c.push("1");
다음과 같은 코드를 보면 당연히 JS에서는 돌아가는 코드일 것입니다. 하지만 다음을 보시죠
let c = [1, 2, 3];
c.push("1");
이는 c배열이 의도한 대로 사용되지 않고 있는 모습을 보고 있는 겁니다. JS에서는 이를 무시하고 runtime Error를 낼 것입니다. 하지만 Typescript에서는 "string을 number type에 대입할 수 없다며 컴파일 오류를 띄우게 되죠" 이는 암묵적으로 typescript에서 c에게 number[]라는 타입을 지정해 주었기 때문입니다. 저희는 이와는 다르게 아래와 같이 명시적으로 타입을 지정해 줄 수도 있습니다.
let Arr: number[] = [1, 2, 3];
Arr.push(1);
다음과 같이 명시적 표현을 통해 typescript가 타입을 추론할 수 있게 할 수 있습니다. 하지만 보통 명시적 표현은 최소한으로 사용하는게 좋습니다. typescript가 추론하게 하는게 더 낫기 때문이죠. 다음의 예시를 보시죠
let Arr: number[] = [1, 2, 3];
Arr.push(1);
const player = {
name: "hyunseo",
};
다음과 같이 작성해 주면 typescript는 player를 아래와 같이 추론하게 됩니다. 이를 암묵적 추론이라고 합니다.
Types of TS - 1
배열은 아래와 같이 타입을 지정해 주게 됩니다.
let a_ = [1, 2];
let b_: string[] = ["il", "1"];
let c_: boolean[] = [true];
객체는 아래와 같이 타입을 지정하게 됩니다. 이떄 Optional Chaining이라는 기술을 사용해 볼 수 있습니다. 그러면 객체에 그 key가 았을 수도, 아니면 없을 수도 있다는 얘기 입니다.
type Player = {
name: string;
age?: number;
};
const player1: Player = {
name: "hyunseo",
};
const palyer2: Player = {
name: "hyunseo2",
age: 21,
};
또한 Player.age의 타입이 ?: 을 해주게 되어 number | undefined가 되었습니다. 따라서 아래와 같이 작성해 주면 오류가 발생하게 됩니다.
type Player = {
name: string;
age?: number;
};
const player1: Player = {
name: "hyunseo",
};
const palyer2: Player = {
name: "hyunseo2",
age: 21,
};
// error
if (player1.age < 10) {
console.log(player1.age);
}
그 이유는 player1에 age라는 속성이 없을 수도 있기 때문이죠, 따라서 아래와 같이 작성해 주어야 합니다.
type Player = {
name: string;
age?: number;
};
const player1: Player = {
name: "hyunseo",
};
const palyer2: Player = {
name: "hyunseo2",
age: 21,
};
if (player1.age && player1.age < 10) {
console.log(player1.age);
}
또한 이러한 객체를 반환하는 함수는 typescript로 아래와 같이 작성해 줄 수 있습니다.
type Player = {
name: string;
age?: number;
};
const player1: Player = {
name: "hyunseo",
};
const palyer2: Player = {
name: "hyunseo2",
age: 21,
};
if (player1.age && player1.age < 10) {
console.log(player1.age);
}
const playerMaker = (name: string): Player => ({
name,
});
const hyunseo = playerMaker("hyunseo3");
hyunseo.age = 22;
이렇게 함수를 반환하는 타입은 명시적으로 함수를 사용할 떄 실수하지 않게 작성해 주는 것이 좋습니다.
Types of TS - 2
다음으로는 readonly가 있습니다. 이는 속성을 바꿀 수 없게 할 수 있습니다. 다음과 같이 말이죠
type Player = {
readonly name: string;
age?: number;
};
const playerMaker = (name: string): Player => ({
name,
});
const hyunseo = playerMaker("hyunseo3");
hyunseo.age = 22;
// error
hyunseo.name = "hyunseo_clone";
같은 원래로 아래 코드도 오류를 내게 됩니다.
const numbers: readonly number[] = [1, 2, 3, 4];
// error
numbers.push(1);
다음은 Tuple 타입입니다. 아래와 같이 원하는 순서에 맞는 타입을 가져야 할 때 사용합니다.
const player: [string, number, boolean] = ["nico", 1, true];
다음은 any타입입니다. any는 타입스크랩트로부터 빠져나오고 싶을 떄 쓰는 타입입니다. 하지만 추천하지는 않는데 아래와 같이 작성될 수 있는 위험이 있기 때문입니다.
let a: any[] = [1, 2, 3, 4];
const b: any = true;
a + b;
이러면 typescript를 쓰는 이유가 없어지므로 매우 이상해 집니다. 하지만 어떠한 특수한 경우 꼭 any가 필요한 경우가 있으므로, 알아둬야 합니다.
Types of TS - 2
never타입은 아직 타입이 정해지지 않았을 때 쓰는 타입입니다 이의 사용예제는 다음과 같습니다.
let a: unknown;
if (typeof a === "number") {
let b = a + 1;
}
if (typeof a === "string") {
let b = a.toUpperCase();
}
꼭 사용할 때는 타입을 확인하고 사용해 주어야 하죠. 이는 변수의 타입을 미리 알지 못할 때 사용합니다.
다음은 void타입입니다. 이는 함수의 반환값이 없을 때 사용합니다. 이의 예제를 보면 이해가 빨리 되실 겁니다. C, C++에서 많이 봤듯이 작성해 주면 됩니다.
function hello(): void {
console.log("x");
}
const a = hello();
// error
a.toUpperCase();
다음과 같이 void에 toUpperCase()를 하면 오류가 뜹니다.
다음은 never타입입니다. 이는 아무것도 반환하지 않아야 할 때 사용합니다. Erorr를 반환하거나 전혀 나와야 하지 않을 곳에서의 변수 명을 지정해 줄 때 말이죠, 아래의 예시를 보시죠
function hello(name: string | number) {
if (typeof name === "string") {
} else if (typeof name === "number") {
} else {
// never
}
}
function Error_return(): never {
throw new Error("hello");
}
'Web > TypeScript' 카테고리의 다른 글
Typescript Practice - Block Chain Project -implements (0) | 2022.05.08 |
---|---|
Typescript Practice - Block Chain Project - Basic (0) | 2022.05.07 |
TypeScript Practice - Class, Interface (0) | 2022.05.07 |
Typescript Practice - Functions (0) | 2022.05.07 |