Typescript 부분적이지만 정의되지 않음
24618 단어 tutorialprogrammingtypescriptwebdev
Partial
는 가장 일반적인 유틸리티 유형 중 하나라고 생각합니다.편리합니다. 속성을 건너뛸 수 있습니다.
예를 들어 데이터베이스의 특정 필드를 업데이트하려면
type abc= Partial<{a:number, b:string, c:boolean}>
const updateDB=(data:abc)=>{}
updateDB({a:1, c:true})
그러나
Partial
는 모든 속성을 undefined
와 통합합니다.updateDB({a:undefined, b:undefined, c:undefined})
playground
모든 사람이 원하는 것은 아니기 때문에 문제가 될 수 있습니다
undefined
. 일부 데이터베이스는 허용할 수 없습니다undefined
(예: Firestore).이 문제를 어떻게 해결할 수 있습니까? 속성을 선택 사항으로 지정하는 동시에 데이터베이스 오염
undefined
을 방지하려면 어떻게 해야 합니까?제네릭 및 매핑된 유형을 사용하여 이 문제를 해결할 수 있습니다.
type abc= {a:number, b:string, c:boolean}
type PartialButNoUndefined <Type extends Record<string,unknown>,Data extends Record<string,unknown>> =
keyof Data extends keyof Type
? {
[K in keyof Data]:Data[K] extends Type[K]?Data[K]:`type of property ${K & string} is incorrect`
}
:`unknown property:${Exclude<keyof Data, keyof Type> & string}`
type allProps = PartialButNoUndefined<abc,{a:1,b:"b",c:true}> // {a: 1, b: "b",c: boolean }
type partialProps = PartialButNoUndefined<abc,{b:"b"}> // { b:string }
type propWithIncorrectValue = PartialButNoUndefined<abc,{a:1, b:true}> // {a,:1, b:"type of property b is incorrect" }
type unknownProps = PartialButNoUndefined<abc,{a:1, z:5, u:true}> // "unknown property:z" | "unknown property:u"
playground
PartialButNoUndefined
가 하는 일:보시다시피 이제 모든 멤버는
undefined
와 결합할 필요 없이 선택 사항입니다.마지막 단계는
PartialButNoUndefined
를 updateDB
함수에 구현하는 것입니다.const updateDB=<T extends Record<string,unknown>>(data:PartialButNoUndefined<abc,T>)=>{}
좋아, 한번 해보자!
updateDB({a: 1, b: "b",c: true }) // expect ok
updateDB({b:"b"}) // expect ok
updateDB({c:undefined}) // expect error
playground
흠, 뭔가 이상해...왜?
이는 Typescript가
T
인수에서 data
를 추론할 수 없기 때문입니다.일반적으로 인수에서 유형을 추론하는 방법을 기억하십시오.
const updateDB=<T extends Record<string,unknown>>(data:T)=>{}
데이터 인수 타입으로 naked type 매개변수를 할당하고 이것이 제네릭 추론이 작동하는 이유입니다(지금은 이것이 정확하지 않고 제네릭 추론은 non-naked type 매개변수에도 작동하지만 지금 그대로 이해하시면 됩니다. 자세히 설명하는 다른 게시물 열기)
하지만 이제 우리는
const updateDB=<T extends Record<string,unknown>>(data:PartialButNoUndefined<abc,T>)=>{}
그러나 이제 데이터 인수 유형으로 기본이 아닌 유형 매개변수
PartialButNoUndefined<abc,T>
를 할당합니다.그래서 우리는 이것을 어떻게 해결할 것입니까?
이제 일반적인 추론이 작동하기 위한 조건, 즉
기본 유형 매개변수를 데이터 인수 유형으로 지정
그리고 우리는 그렇게 할 것입니다
const updateDB=<T extends Record<string,unknown>>(data:T extends never? T: PartialButNoUndefined<abc,T>)=>{}
playground
그리고 붐, 작동합니다!
하지만 어떻게? 무슨 일이야?
재검토 해보자:
T
을 data
인수에 할당해야 한다는 것이 분명합니다T
을 data
유형으로 사용하고 싶지 않고 PartialButNoUndefined<abc,T>
우리의 data
유형data: T extends never? T: PartialButNoUndefined<abc,T>
는 Typescript에 다음과 같이 말합니다.이는
data
가 PartialButNoUndefined<abc,T>
확장되지 않고 조건이 T
를 유형으로 반환하기 때문에 가능합니다.즉, 이제
never
에 대해 걱정할 필요 없이 선택적 유형을 만들 수 있습니다.마지막으로 첫 번째를 단순화하겠습니다. 이제 유형 검사에 의존할 수 있으므로 설명 유형을 삭제할 수 있습니다.
type abc= {a:number, b:string, c:boolean}
type PartialButNoUndefined <Type extends Record<string,unknown>,Data extends Record<string,unknown>> =
{
[K in keyof Data]: Type[K extends keyof Type ? K:never]
}
const updateDB=<T extends Record<string,unknown>>(data:T extends never? T: PartialButNoUndefined<abc,T>)=>{}
updateDB({a: 1, b: "b",c: true }) // ok
updateDB({b:"b"}) // ok
updateDB({a:true, b:"abc",c:undefined}) // expect error
updateDB({b:"abc",z:1}) // expect error
playground
이것은 더 깨끗해 보이고 더 간결한 유형 검사가 있습니다.
PartialButNoUndefined<abc,T>
를 제거하면 흥미로운 점이 있습니다.type abc= {a:number, b:string, c:boolean}
type PartialButNoUndefined <Type extends Record<string,unknown>, Data extends Record<string,unknown>> =
{
[K in keyof Data]: Type[K extends keyof Type ? K:never]
}
const updateDB=<T extends Record<string,unknown>>(data: PartialButNoUndefined<abc,T>)=>{}
updateDB({a: 1, b: "b",c: true }) // ok
updateDB({b:"b"}) // ok
updateDB({a:true, b:"abc",c:undefined}) // expect error
updateDB({b:"abc",z:1}) // expect error
playground
여전히 작동합니다
그러나 왜 더 일찍 작동하지 않고
undefined
에 의존해야 합니까?불행히도 나는 모른다. 그러한 행동은 문서에 설명되어 있지 않지만 아마도 내가 모르는 어떤 패치 노트에 설명되어 있을 것이다.
이유 아시는분은 댓글 달아주세요
업데이트: 오늘 작업을 더 간단하게 수행할 수 있는 방법이 있습니다: exactOptionalPropertyTypes
Reference
이 문제에 관하여(Typescript 부분적이지만 정의되지 않음), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tylim88/typescript-partial-but-no-undefined-55d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)