TypeScript는 JavaScript를 기반으로 구축된 강력한 형식의 프로그래밍 언어로 어떤 규모에서든 더 나은 도구를 제공한다고 주장합니다. 그러나 암시적으로 코드베이스에 몰래 들어가 TypeScript의 많은 장점을 잃을 수 있는 유형이 포함되어 있습니다. TypeScript에는 any 이 문서에서는 TypeScript 프로젝트의 유형을 제어하는 방법을 살펴봅니다. TypeScript의 강력한 기능을 활용하여 최고의 유형 안전성을 달성하고 코드 품질을 향상할 준비를 하세요. any TypeScript에서 Any를 사용할 때의 단점 TypeScript는 개발자 경험과 생산성을 향상시키기 위한 다양한 추가 도구를 제공합니다. 개발 단계 초기에 오류를 잡는 데 도움이 됩니다. 코드 편집기 및 IDE에 탁월한 자동 완성 기능을 제공합니다. 환상적인 코드 탐색 도구와 자동 리팩토링을 통해 대규모 코드베이스를 쉽게 리팩토링할 수 있습니다. 유형을 통해 추가 의미 체계와 명시적 데이터 구조를 제공하여 코드베이스에 대한 이해를 단순화합니다. 그러나 코드베이스에서 유형을 사용하기 시작하자마자 위에 나열된 모든 이점을 잃게 됩니다. 유형은 유형 시스템의 위험한 허점이며 이를 사용하면 모든 유형 검사 기능은 물론 유형 검사에 의존하는 모든 도구도 비활성화됩니다. 결과적으로 TypeScript의 모든 이점이 사라집니다. 버그가 누락되고 코드 편집기의 유용성이 떨어지는 등의 일이 발생합니다. any any 예를 들어 다음 예를 고려해보세요. function parse(data: any) { return data.split(''); } // Case 1 const res1 = parse(42); // ^ TypeError: data.split is not a function // Case 2 const res2 = parse('hello'); // ^ any 위의 코드에서: 기능 내에서 자동 완성을 놓칠 수 있습니다. 편집기에서는 에 사용 가능한 방법에 대한 올바른 제안이 제공되지 않습니다. parse data. data 첫 번째 경우에는 문자열 대신 숫자를 전달했기 때문에 오류가 발생합니다. 유형 검사를 비활성화하므로 TypeScript는 오류를 강조 표시할 수 없습니다. TypeError: data.split is not a function any 두 번째 경우에는 변수에도 유형이 있습니다. 이는 의 단일 사용이 코드베이스의 많은 부분에 계단식 영향을 미칠 수 있음을 의미합니다. res2 any any 극단적인 경우나 프로토타입 제작이 필요한 경우 것을 사용해도 괜찮습니다. 일반적으로 TypeScript를 최대한 활용하려면 사용하지 않는 것이 좋습니다. any any 모든 유형이 나오는 곳 명시적으로 작성하는 것이 유일한 옵션은 아니기 때문에 코드베이스에서 유형의 소스를 알고 있는 것이 중요합니다. 유형을 사용하지 않으려는 최선의 노력에도 불구하고 때때로 암시적으로 코드베이스에 몰래 들어갈 수 있습니다. any any any 코드베이스에는 유형의 네 가지 주요 소스가 있습니다. any tsconfig의 컴파일러 옵션. TypeScript의 표준 라이브러리. 프로젝트 종속성. 코드베이스에서 를 명시적으로 사용합니다. any 나는 이미 과 처음 두 가지 사항에 대한 대한 기사를 작성했습니다. 프로젝트의 형식 안전성을 향상하려면 이 내용을 확인하세요. tsconfig의 주요 고려 사항 표준 라이브러리 유형 개선에 이번에는 코드베이스에서 유형의 모양을 제어하는 자동 도구에 중점을 둘 것입니다. any 1단계: ESLint 사용 는 모범 사례와 코드 형식을 보장하기 위해 웹 개발자가 사용하는 널리 사용되는 정적 분석 도구입니다. 코딩 스타일을 적용하고 특정 지침을 따르지 않는 코드를 찾는 데 사용할 수 있습니다. ESLint 플러그인 덕분에 ESLint를 TypeScript 프로젝트에서도 사용할 수 있습니다. 아마도 이 플러그인은 프로젝트에 이미 설치되어 있을 것입니다. 하지만 그렇지 않은 경우 공식 따를 수 있습니다. typectipt-eslint 시작 가이드를 의 가장 일반적인 구성은 다음과 같습니다. typescript-eslint module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', ], plugins: ['@typescript-eslint'], parser: '@typescript-eslint/parser', root: true, }; 이 구성을 사용하면 구문 수준에서 TypeScript를 이해할 수 있으므로 코드에서 수동으로 작성된 유형에 적용되는 간단한 eslint 규칙을 작성할 수 있습니다. 예를 들어, 명시 . eslint any 사전 설정에는 코드 정확성 향상을 목표로 신중하게 선택된 ESLint 규칙 세트가 포함되어 있습니다. 전체 사전 설정을 사용하는 것이 권장되지만 이 문서에서는 규칙에만 중점을 둘 것입니다. recommended no-explicit-any 명시적이지 않은 것 TypeScript의 엄격 모드는 묵시적인 사용을 금지하지만 명시적으로 사용을 금지하지는 않습니다. 규칙은 코드베이스의 곳에도 수동으로 작성하는 것을 금지하는 데 도움이 됩니다. any any no-explicit-any any // ❌ Incorrect function loadPokemons(): any {} // ✅ Correct function loadPokemons(): unknown {} // ❌ Incorrect function parsePokemons(data: Response<any>): Array<Pokemon> {} // ✅ Correct function parsePokemons(data: Response<unknown>): Array<Pokemon> {} // ❌ Incorrect function reverse<T extends Array<any>>(array: T): T {} // ✅ Correct function reverse<T extends Array<unknown>>(array: T): T {} 이 규칙의 주요 목적은 팀 전체에서 사용하지 못하도록 방지하는 것입니다. 이는 프로젝트에서 사용하지 않는 것이 좋다는 팀의 합의를 강화하는 수단입니다. any any 것을 한 번만 사용해도 으로 인해 코드베이스의 상당 부분에 연쇄적인 영향을 미칠 수 있으므로 이는 중요한 목표입니다. 그러나 이는 여전히 궁극적인 유형 안전성을 달성하는 것과는 거리가 멀습니다. any 유형 추론 명시적이지 않은 것만으로는 충분하지 않은 이유 명시적으로 사용된 다루었지만 npm 패키지 및 TypeScript의 표준 라이브러리를 포함하여 프로젝트의 종속성 내에 암시된 여전히 많이 있습니다. any any 모든 프로젝트에서 볼 수 있는 다음 코드를 고려해보세요. const response = await fetch('https://pokeapi.co/api/v2/pokemon'); const pokemons = await response.json(); // ^? any const settings = JSON.parse(localStorage.getItem('user-settings')); // ^? any 변수 과 모두 암시적으로 유형이 지정되었습니다. 이 경우 나 TypeScript의 엄격 모드는 우리에게 경고하지 않습니다. 아직 아님. pokemons settings any no-explicit-any 이는 및 의 유형이 TypeScript의 표준 라이브러리에서 오기 때문에 발생합니다. 여기서 이러한 메서드에는 명시적인 주석이 있습니다. 변수에 대해 더 나은 유형을 수동으로 지정할 수 있지만 표준 에는 거의 1,200번의 유형이 있습니다. 표준 라이브러리에서 우리 코드베이스로 들어올 수 있는 모든 경우를 기억하는 것은 거의 불가능합니다. response.json() JSON.parse() any any any 외부 종속성도 마찬가지입니다. npm에는 형식이 잘못된 라이브러리가 많이 있으며 대부분은 여전히 JavaScript로 작성됩니다. 결과적으로 이러한 라이브러리를 사용하면 코드베이스에 많은 암시적 쉽게 발생할 수 있습니다. any 일반적으로 우리 코드에 들어갈 수 있는 방법은 여전히 많습니다. any 2단계: 유형 검사 기능 강화 이상적으로는 어떤 이유로든 유형을 받은 모든 변수에 대해 컴파일러가 불평하도록 TypeScript에 설정을 갖고 싶습니다. 불행하게도 그러한 설정은 현재 존재하지 않으며 추가될 것으로 예상되지 않습니다. any 플러그인의 유형 확인 모드를 사용하여 이 동작을 달성할 수 있습니다. 이 모드는 TypeScript와 함께 작동하여 TypeScript 컴파일러에서 ESLint 규칙까지 완전한 유형 정보를 제공합니다. 이 정보를 사용하면 TypeScript의 유형 검사 기능을 기본적으로 확장하는 더 복잡한 ESLint 규칙을 작성할 수 있습니다. 예를 들어, 규칙은 를 얻은 방법에 관계없이 유형의 모든 변수를 찾을 수 있습니다. typescript-eslint any any 유형 인식 규칙을 사용하려면 ESLint 구성을 약간 조정해야 합니다. module.exports = { extends: [ 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-type-checked', ], plugins: ['@typescript-eslint'], parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + tsconfigRootDir: __dirname, + }, root: true, }; 에 대한 유형 추론을 활성화하려면 ESLint 구성에 추가하세요. 그런 다음 사전 설정을 로 바꿉니다. 후자의 사전 설정은 약 17개의 새로운 강력한 규칙을 추가합니다. 이 기사에서는 그 중 5가지에만 중점을 둘 것입니다. typescript-eslint parserOptions recommended recommended-type-checked 안전하지 않은 인수 규칙은 유형의 변수가 매개변수로 전달되는 함수 호출을 검색합니다. 이런 일이 발생하면 유형 검사가 손실되고 강력한 유형 지정의 모든 이점도 손실됩니다. no-unsafe-argument any 예를 들어, 객체를 매개변수로 요구하는 함수를 생각해 보겠습니다. JSON을 수신하여 구문 분석하고 유형을 얻는다고 가정합니다. saveForm any // ❌ Incorrect function saveForm(values: FormValues) { console.log(values); } const formValues = JSON.parse(userInput); // ^? any saveForm(formValues); // ^ Unsafe argument of type `any` assigned // to a parameter of type `FormValues`. 이 매개변수를 사용하여 함수를 호출하면 규칙은 이를 안전하지 않은 것으로 플래그 지정하고 변수에 대해 적절한 유형을 지정하도록 요구합니다. saveForm no-unsafe-argument value 이 규칙은 함수 인수 내에 중첩된 데이터 구조를 심층적으로 검사할 만큼 강력합니다. 따라서 객체를 함수 인수로 전달하면 형식화되지 않은 데이터가 절대 포함되지 않을 것이라고 확신할 수 있습니다. // ❌ Incorrect saveForm({ name: 'John', address: JSON.parse(addressJson), // ^ Unsafe assignment of an `any` value. }); 오류를 해결하는 가장 좋은 방법은 TypeScript의 나 또는 와 같은 유효성 검사 라이브러리를 사용하는 것입니다. 예를 들어, 구문 분석된 데이터의 정확한 유형을 좁히는 함수를 작성해 보겠습니다. 유형 축소 Zod Superstruct parseFormValues // ✅ Correct function parseFormValues(data: unknown): FormValues { if ( typeof data === 'object' && data !== null && 'name' in data && typeof data['name'] === 'string' && 'address' in data && typeof data.address === 'string' ) { const { name, address } = data; return { name, address }; } throw new Error('Failed to parse form values'); } const formValues = parseFormValues(JSON.parse(userInput)); // ^? FormValues saveForm(formValues); 알 수 허용하는 함수에 대한 인수로 유형을 전달하는 것이 허용됩니다. 그렇게 하는 것과 관련된 안전 문제가 없기 때문입니다. unknown any 데이터 유효성 검사 함수를 작성하는 것은 지루한 작업이 될 수 있으며, 특히 대량의 데이터를 처리할 때 더욱 그렇습니다. 따라서 데이터 검증 라이브러리의 사용을 고려해 볼 가치가 있습니다. 예를 들어 Zod를 사용하면 코드는 다음과 같습니다. // ✅ Correct import { z } from 'zod'; const schema = z.object({ name: z.string(), address: z.string(), }); const formValues = schema.parse(JSON.parse(userInput)); // ^? { name: string, address: string } saveForm(formValues); 안전하지 않은 할당 규칙은 값이 유형인 변수 할당을 검색합니다. 이러한 할당은 컴파일러가 변수에 특정 유형이 있다고 생각하도록 오해할 수 있지만 데이터는 실제로 다른 유형을 가질 수 있습니다. no-unsafe-assignment any JSON 구문 분석의 이전 예를 고려하십시오. // ❌ Incorrect const formValues = JSON.parse(userInput); // ^ Unsafe assignment of an `any` value 규칙 덕분에 다른 곳에 전달하기 전에도 유형을 포착할 수 있습니다. 수정 전략은 동일하게 유지됩니다. 유형 축소를 사용하여 변수 값에 특정 유형을 제공할 수 있습니다. no-unsafe-assignment formValues any // ✅ Correct const formValues = parseFormValues(JSON.parse(userInput)); // ^? FormValues 안전하지 않은 회원 액세스 및 안전하지 않은 호출 없음 이 두 규칙은 훨씬 덜 자주 실행됩니다. 그러나 내 경험에 따르면 형식이 잘못된 타사 종속성을 사용하려고 할 때 정말 도움이 됩니다. 규칙은 변수에 유형이 있는 경우 이거나 수 있으므로 객체 속성에 액세스하지 못하게 합니다. no-unsafe-member-access any null undefined 규칙은 함수가 아닐 수도 있는 유형의 변수를 함수로 호출하는 것을 방지합니다. no-unsafe-call any 라는 잘못된 유형의 타사 라이브러리가 있다고 가정해 보겠습니다. untyped-auth // ❌ Incorrect import { authenticate } from 'untyped-auth'; // ^? any const userInfo = authenticate(); // ^? any ^ Unsafe call of an `any` typed value. console.log(userInfo.name); // ^ Unsafe member access .name on an `any` value. Linter는 두 가지 문제를 강조합니다. 함수를 호출하는 것은 중요한 인수를 함수에 전달하는 것을 잊어버릴 수 있으므로 안전하지 않을 수 있습니다. authenticate 개체에서 속성을 읽는 것은 인증이 실패하면 이 되므로 안전하지 않습니다. userInfo name null 이러한 오류를 해결하는 가장 좋은 방법은 강력한 형식의 API가 포함된 라이브러리 사용을 고려하는 것입니다. 그러나 이것이 옵션이 아닌 경우 수 있습니다. 고정 라이브러리 유형의 예는 다음과 같습니다. 라이브러리 유형을 직접 늘릴 // ✅ Correct import { authenticate } from 'untyped-auth'; // ^? (login: string, password: string) => Promise<UserInfo | null> const userInfo = await authenticate('test', 'pwd'); // ^? UserInfo | null if (userInfo) { console.log(userInfo.name); } 안전하지 않은 반품 규칙은 좀 더 구체적인 것을 반환해야 하는 함수에서 실수로 유형을 반환하지 않도록 도와줍니다. 이러한 경우 컴파일러는 반환된 값에 특정 유형이 있다고 잘못 생각하지만 데이터에는 실제로 다른 유형이 있을 수 있습니다. no-unsafe-return any 예를 들어 JSON을 구문 분석하고 두 가지 속성이 있는 객체를 반환하는 함수가 있다고 가정해 보겠습니다. // ❌ Incorrect interface FormValues { name: string; address: string; } function parseForm(json: string): FormValues { return JSON.parse(json); // ^ Unsafe return of an `any` typed value. } const form = parseForm('null'); console.log(form.name); // ^ TypeError: Cannot read properties of null 함수는 구문 분석된 값을 확인하지 않기 때문에 사용되는 프로그램의 모든 부분에서 런타임 오류가 발생할 수 있습니다. 규칙은 이러한 런타임 문제를 방지합니다. parseForm no-unsafe-return 구문 분석된 JSON이 예상 유형과 일치하는지 확인하는 유효성 검사를 추가하면 이 문제를 쉽게 해결할 수 있습니다. 이번에는 Zod 라이브러리를 사용해 보겠습니다. // ✅ Correct import { z } from 'zod'; const schema = z.object({ name: z.string(), address: z.string(), }); function parseForm(json: string): FormValues { return schema.parse(JSON.parse(json)); } 성능에 대한 참고 사항 유형 확인 규칙을 사용하면 모든 유형을 추론하기 위해 TypeScript의 컴파일러를 호출해야 하기 때문에 ESLint에 대한 성능 저하가 발생합니다. 이러한 감속은 주로 커밋 전 후크와 CI에서 linter를 실행할 때 눈에 띄지만 IDE에서 작업할 때는 눈에 띄지 않습니다. 유형 검사는 IDE 시작 시 한 번 수행된 다음 코드를 변경하면 유형을 업데이트합니다. 단순히 유형을 추론하는 것이 일반적인 컴파일러 호출보다 빠르게 작동한다는 점은 주목할 가치가 있습니다. 예를 들어 약 150만 줄의 TypeScript 코드가 포함된 가장 최근 프로젝트에서 통한 유형 검사에는 약 11분이 소요되는 반면, ESLint의 유형 인식 규칙이 부트스트랩하는 데 필요한 추가 시간은 약 2분에 불과합니다. tsc tsc 우리 팀의 경우 유형 인식 정적 분석 규칙을 사용하여 추가적인 안전성을 제공하는 것은 그만한 가치가 있습니다. 소규모 프로젝트에서는 이 결정을 내리는 것이 훨씬 더 쉽습니다. 결론 TypeScript 프로젝트에서 사용을 제어하는 것은 최적의 유형 안전성과 코드 품질을 달성하는 데 중요합니다. 플러그인을 활용하면 개발자는 코드베이스에서 유형의 발생을 식별하고 제거하여 더욱 강력하고 유지 관리 가능한 코드베이스를 만들 수 있습니다. any typescript-eslint any 유형 인식 eslint 규칙을 사용하면 코드 베이스에 키워드가 나타나는 것은 실수나 실수가 아니라 의도적인 결정이 됩니다. 이 접근 방식은 표준 라이브러리 및 타사 종속성뿐만 아니라 자체 코드에서도 사용하지 못하도록 보호합니다. any any 전반적으로 유형 인식 린터를 사용하면 Java, Go, Rust 등과 같은 정적으로 유형이 지정된 프로그래밍 언어와 유사한 수준의 유형 안전성을 달성할 수 있습니다. 이는 대규모 프로젝트의 개발 및 유지 관리를 크게 단순화합니다. 이 기사에서 새로운 것을 배웠기를 바랍니다. 읽어 주셔서 감사합니다! 유용한 링크 라이브러리: typescript-eslint 문서: tsconfig의 주요 고려 사항 기사: 표준 라이브러리 유형 개선 문서: TypeScript에서 유형 축소 문서: TypeScript의 유형 추론 도서관: 조드 라이브러리: 슈퍼스트럭트