TypeScript Type Guard를 안전하고 최신 상태로 유지(간단한 솔루션)
12674 단어 typescripttypeguard
사진 제공: Brian McGowan on Unsplash
유형 가드를 사용하면 런타임, 알 수 없는 개체(백엔드에서 오는 데이터를 생각)가 지정된 유형을 존중하는지 확인할 수 있습니다. 유형 가드는
unknown
매개변수를 받고, 모든 속성이 있는지 확인하고, 특정 유형을 존중하는 개발자가 작성한 함수에 지나지 않습니다. 따라서 TypeScript는 매개변수가 올바르게 입력되었다고 안전하게 가정할 수 있습니다.예: 주어진 유형
interface Person {
name: string
age: number
}
이것은 위의 유형 가드입니다
Person
.function isPerson(value: unknown): value is Person {
return (
typeof value === 'object' &&
value &&
value.hasOwnProperty('name') &&
value.hasOwnProperty('age') &&
typeof value.name === 'string' &&
typeof value.age === 'number'
)
}
위 유형 가드의 주요 문제점은 무엇입니까? 확장되지 않습니다.
Person
유형을 업데이트하면 TypeScript가 오류를 발생시키지 않습니다. 유형을 다음으로 변경한다고 상상해보십시오.interface Person {
name: string
age: number
something: string // <-- a new property
}
TypeScript는 불평하지 않지만
isPerson
함수는 이제 구식입니다.그의 TypeScript: Keeping Type Guards Safe and Up To Date 기사(제목을 훔쳤습니다. 죄송합니다, Michal)에서 이 문제를 이미 논의했으며 스케일링 작업 솔루션을 제안했습니다.
문제와 그 해결책을 완전히 이해하려면 그의 기사를 읽으십시오. 이 기사에서는 그의 접근 방식을 약간의 차이를 두고 사용하여 (제 생각에는) 더 간단한 솔루션에 도달했습니다. 차이점은 다음과 같습니다.
isPlainObject
를 확장하는 대신 global.object
유형 가드 사용isPerson
1. global.object를 확장하는 대신 isPlainObject 유형 가드 사용
가능한 한 TypeScript의 전역 확장을 피합니다. 다음
isPlainObject
은 TypeScript가 hasOwn
/hasOwnProperty
를 통해 확인된 속성이 사실상 개체 자체의 일부이지만 global.object
를 확장하지 않는다는 것을 인식할 수 있는 간단한 해결 방법입니다.interface PlainObject {
hasOwnProperty<K extends string>(key: K): this is Record<K, unknown>
// Object.hasOwn() is intended as a replacement for Object.hasOwnProperty(). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
hasOwn<K extends string>(key: K): this is Record<K, unknown>
}
function isPlainObject(value: unknown): value is PlainObject {
return !!value && typeof value === 'object' && !Array.isArray(value)
}
2. isPerson을 실제 유형 가드로 되돌리기
Michal은 구문 분석기를 만든 다음 이를 사용하여 유형 가드를 만들 것을 제안했습니다. 내 제안은 파서의 특전(확장 가능한 유형 가드)과 표준 유형 가드(단순성)를 활용하는 것입니다.
이것은 두 가지 접근 방식을 혼합한 결과입니다.
function isPerson(value: unknown): value is Person {
if (!isPlainObject(value)) return false
if (!value.hasOwnProperty('name')) return false
if (!value.hasOwnProperty('age')) return false
const { name, age } = value
if (typeof name !== 'string') return false
if (typeof age !== 'number') return false
// @ts-expect-error: turn off "obj is declared but never used."
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const obj: Person = { name, age }
return true
}
대부분의 마법은 다음 줄에서 나옵니다.
// @ts-expect-error: turn off "obj is declared but never used."
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const obj: Person = { name, age }
매번 새 개체를 만들고 반환하는 Michal의 솔루션이 마음에 들지 않았기 때문에 이것은 필요합니다. 나는 기계의 메모리를 많이 사용하는 응용 프로그램 작업에 익숙하며 생성하는 개체가 적을수록 좋습니다. 객체를 생성하는 것과 객체를 반환하는 것의 차이점은 무엇입니까?
(V8 팀에서 작업한 크롬 브라우저 내부의 Javascript VM) 비소비 변수(다른 함수에 전달되지 않고 반환되지 않는 변수)와 관련된 코드가 함수를 떠나지 않는다고 장담합니다. 다른 범위와 공유되지 않으며 런타임 관점에서 완전히 쓸모가 없기 때문에 컴파일 시간에 제거됩니다. 따라서 개체는 런타임에 생성되지 않으며 가비지 수집기 또는 보육원을 통과하지 않습니다.
이TypeScript playground에서 위의 예를 가지고 놀 수도 있습니다. 여기에서 선택적 속성을 추가하여 어떻게 관리할 수 있는지 보여줍니다.
업데이트
새로운 선택적 속성으로부터 보호하는 데 도움이 되는 작은 변화도 살펴보세요 😊
결론
his solution으로 눈을 뜨게 해준 , Michal의 구현을 발전시키는 데 도움을 준 , JS VM에 대한 내부 정보를 제공한 에게 감사합니다.
Reference
이 문제에 관하여(TypeScript Type Guard를 안전하고 최신 상태로 유지(간단한 솔루션)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/noriste/keeping-typescript-type-guards-safe-and-up-to-date-a-simpler-solution-ja3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)