Loading the catalog…
Loading the catalog…
『실무로 통하는 타입스크립트』 Boolean 생성자로 null/undefined 제거하기 배열에서 null 종류의 값을 거르는 Boolean 생성자를 사용하려는데, TypeScript는 여전히 null 과 undefined 를 포함한 같은 타입을 반환한다. const array = [1, 2, 3, undefined, 4, null]; const filtered = array.filter((val) => !!val); 직접 확인한 결과, filtered 의 타입은 여전히 (number | null | undefined)[] 다. 런타임에서는 실제로 걸러졌어도, 타입 시스템은 필터 콜백의 로직까지 분석하지 못해서 원본과 같은 타입을 그대로 돌려준다. 해결 : 선언 합치기로 Array 의 filter 메서드를 오버로드한다. declare global { interface Array<T> { filter(predicate: BooleanConstructor): NonNullable<T>[]; } interface ReadonlyArray<T> { filter(predicate: BooleanConstructor): NonNullable<T>[]; } } // BooleanConstructor는 Boolean 생성자 자체의 타입이다 (typeof Boolean). // 즉 predicate 자리에 Boolean을 "그대로" 넘긴 특정 호출만 이 오버로드가 잡아낸다. const filtered2 = array.filter(Boolean); 직접 검증한 결과, filtered2 는 정확히 number[] 로 좁혀졌다. falsy 값까지 제거하는 Truthy BooleanConstructor 는 falsy한 값( "" , false , 0 , 0n , null , undefined )을 전부 거른다. 그런데 NonNullable<T> 는 null / undefined 만 제거할 뿐, 나머지 falsy 값( 0 , false , "" )은 타입에 그대로 남는다. type Truthy<T> = T extends "" | false | 0 | 0n ? never : T; declare global { interface Array<T> { filter(predicate: BooleanConstructor): Truthy<NonNullable<T>>[]; } interface ReadonlyArray<T> { filter(predicate: BooleanConstructor): Truthy<NonNullable<T>>[]; } } const nullOrOne: Array<0 | 1> = [0, 1, 0, 1]; const onlyOnes = nullOrOne.filter(Boolean); // onlyOnes: 1[] 직접 확인한 결과, 0 | 1 에서 0 이 제거되고 1[] 만 남았다. 라이브러리 타입 정의 패치하기 — 모듈 선언 합치기 Preact나 React 같은 라이브러리를 사용 중인데, 타입 정의가 최신 기능을 포함하지 않을 때가 있어 패치하고 싶다. 해결 : 모듈과 인터페이스 수준에서 선언 합치기를 한다. @types 폴더를 만들고 jsx.d.ts 파일을 추가한다. compilerOptions.types 에 해당 경로를 설정한다. 원하는 정의를 추가한다. import "react"; declare module "react" { interface ImgHTMLAttributes<T> extends HTMLAttributes<T> { loading?: "lazy" | "eager" | "auto"; alt: string; } } declare / module / namespace의 차이 키워드 역할 declare "이 코드는 어딘가에 실제로 존재하지만, 그 구현은 여기 없다"는 선언. 타입 정보만 컴파일러에 알려준다 declare module "이름" 특정 모듈 (파일 또는 패키지)의 타입을 선언하거나 확장한다 declare namespace 전역에 네임스페이스 (이름 묶음)를 선언한다. 레거시 JS 라이브러리(jQuery 등)처럼 전역 변수 하나에 여러 기능을 매달아 쓰던 패턴을 타이핑할 때 주로 쓴다 declare global 모듈 안에서 전역 스코프 를 확장한다 그 밖에 declare const (변수), declare function (함수), declare class (클래스)도 있다. 이들을 묶어 주변 선언(ambient declaration) 이라 부른다. 아직 지원되지 않는 브라우저 기능 타이핑하기 ResizeObserver 같은 브라우저 기능을 썼는데, 현재 TypeScript 설정에서 해당 기능을 사용할 수 없다. 해결 : 전역 네임스페이스에 사용자 정의 타입 정의를 추가한다. lib.dom.d.ts 업데이트를 기다릴 수 없다면 직접 타입을 추가할 수 있다. // resize-observer.d.ts declare var ResizeObserver: { prototype: ResizeObserver; new (callback: ResizeObserverCallback): ResizeObserver; }; 어디에서나 사용하려면 declare global 로 감싼다. declare global { var ResizeObserver: { prototype: ResizeObserver; new (callback: ResizeObserverCallback): ResizeObserver; }; } resize-observer.d.ts 를 @types 폴더에 넣고 typeRoots , include 에 경로를 설정한다. 존재하지 않을 수도 있다는 걸 타입으로 표현하기 대상 브라우저에서 ResizeObserver 를 아직 사용할 수 없을 가능성이 있다면, 정의되지 않은 상태( undefined )일 수 있다는 걸 타입에 포함시킨다. declare global { var ResizeObserver: | { prototype: ResizeObserver; new (callback: ResizeObserverCallback): ResizeObserver; } | undefined; } 타입에 | undefined 를 추가하면, "이 전역 객체는 없을 수도 있다"는 정보가 컴파일러에 전달된다. 그래서 체크 없이 바로 쓰면 에러가 나고, 런타임에 실제로 존재하는지 확인한 뒤에만 쓰도록 강제된다. const x = ResizeObserver.prototype; // TS18048: 'ResizeObserver' is possibly 'undefined' if (typeof ResizeObserver !== "undefined") { const x = new ResizeObserver((entries) => {}); // 통과 } 직접 검증한 결과, 체크 없는 접근은 정확히 이 에러로 막히고, typeof 체크를 거치면 정상적으로 좁혀져 통과한다. "객체를 사용할 수 있는지 확인할 수 있다"는 말은 이 런타임 존재 여부 검사를 타입 시스템이 강제한다 는 뜻이다. 엠비언트 선언 파일을 TypeScript가 인식하지 못할 때 확인할 것 include 속성에 @types 폴더 경로가 포함되어 있는지 확인한다. 여기 포함돼 있어야 컴파일러가 그 폴더의 .d.ts 파일들을 읽어 타입 검사 대상으로 삼는다 ( "파싱한다" 는 이 과정, 즉 폴더 안의 선언 파일들을 읽어 들여 분석한다는 뜻이다). 엠비언트 파일을 types 나 typeRoots 에 추가한다. 엠비언트 파일 끝에 export {} 를 추가하면 TypeScript가 그 파일을 모듈로 인식한다. 직접 확인한 결과, export {} 가 없으면 declare global 자체가 TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations 에러로 막힌다. declare global 은 모듈 안에서만 쓸 수 있는 문법이기 때문이다. 번들러로 불러온 비-JS 파일 타이핑하기 (.css, 이미지 등) 웹팩 같은 번들러로 JavaScript에서 .css 나 이미지 같은 파일을 불러왔는데, TypeScript는 이러한 파일을 인식하지 못한다. 해결 : 파일명 확장자에 기반해 모듈을 전역으로 선언한다. TypeScript는 환경에 있거나 도구를 통해 접근할 수 있는 모듈에도 엠비언트 모듈 선언 을 지원한다 ( url , http , path 같은 Node 주요 내장 모듈 등). 와일드카드 패턴에도 사용할 수 있다. declare module "*.css" { interface IClassNames { [className: string]: string; } const classNames: IClassNames; export default classNames; } 임포트하려는 모든 .css 파일을 이 선언이 인식한다. 다만 자동완성에서 정확한 클래스 이름까지는 알 수 없다. NPM 패키지를 추가로 설치하면 타입 파일을 자동으로 생성해 해결할 수 있다. 이 밖에 *.mdx 를 선언하면 JSX 파일에서 컴포넌트로 사용할 수 있다. 앰비언트 모듈을 사용하려면 @types 폴더를 만드는 게 좋다. 이 폴더에 모듈 정의가 포함된 .d.ts 파일을 얼마든지 추가할 수 있다. typeRoots 옵션으로 @types 경로를 설정한다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
2026.10.03 1일 1로그. 『실무로 통하는 타입스크립트』 Boolean 생성자로 null/undefined 제거하기 배열에서 null 종류의 값을 거르는 Boolean 생성자를 사용하려는데, TypeScript는 여전히 null 과 undefined 를 포함한 같은 타입을 반환한다. const array = [1, 2, 3, undefined, 4, null]; const filtered = array.filter((val) => !!val); 직접 확인한 결과, filtered 의 타입은 여전히 (number | null | undefined)[] 다. 런타임에서는 실제로 걸러졌어도, 타입 시스템은 필터 콜백의 로직까지 분석하지 못해서 원본과 같은 타입을 그대로 돌려준다. 해결 : 선언 합치기로…
Open source