Typescript: 정확한 유형

에 만든 2016년 12월 15음  Â·  171윔멘튞  Â·  출처: microsoft/TypeScript

읎것은 정확한 유형에 대한 구묞을 활성화하Ʞ 위한 제안입니닀. Flow(https://flowtype.org/docs/objects.html#exact-object-types)에서도 비슷한 Ʞ능을 볌 수 있지만 읞터페읎슀가 아닌 타입 늬터럎에 사용되는 Ʞ능윌로 제안하고 싶습니닀. ë‚Žê°€ 제안한 특정 구묞은 수학적 절대 구묞에 익숙하Ʞ 때묞에 파읎프(Flow 구현을 거의 믞러링하지만 type 묞을 둘러싞알 핹)입니닀.

interface User {
  username: string
  email: string
}

const user1: User = { username: 'x', email: 'y', foo: 'z' } //=> Currently errors when `foo` is unknown.
const user2: Exact<User> = { username: 'x', email: 'y', foo: 'z' } //=> Still errors with `foo` unknown.

// Primary use-case is when you're creating a new type from expressions and you'd like the
// language to support you in ensuring no new properties are accidentally being added.
// Especially useful when the assigned together types may come from other parts of the application 
// and the result may be stored somewhere where extra fields are not useful.

const user3: User = Object.assign({ username: 'x' }, { email: 'y', foo: 'z' }) //=> Does not currently error.
const user4: Exact<User> = Object.assign({ username: 'x' }, { email: 'y', foo: 'z' }) //=> Will error as `foo` is unknown.

읎 구묞 변겜은 새로욎 Ʞ능읎며 맀개변수 또는 녞출된 유형윌로 사용되는 겜우 작성되는 새 정의 파음에 영향을 믞칩니닀. 읎 구묞은 더 복잡한 닀륞 유형곌 결합될 수 있습니닀.

type Foo = Exact<X> | Exact<Y>

type Bar = Exact<{ username: string }>

function insertIntoDb (user: Exact<User>) {}

읎것읎 쀑복읎띌멎 믞늬 사곌드늜니닀. 읎 Ʞ능의 쀑복을 찟는 데 적합한 킀워드륌 찟지 못한 것 같습니닀.

펞집: 읎 게시묌은 https://github.com/Microsoft/TypeScript/issues/12936#issuecomment -267272371에 얞꞉된 Ʞ볞 구묞 제안을 사용하도록 업데읎튞되었습니닀. 여Ʞ에는 식에서 사용할 수 있도록 음반 유형곌 핚께 더 ê°„ë‹ší•œ 구묞을 사용하는 것읎 포핚됩니닀.

Awaiting More Feedback Suggestion

가장 유용한 댓Ꞁ

우늬는 읎것에 대핮 ꜀ 였랫동안 읎알Ʞ했습니닀. 나는 토론을 요앜하렀고 녞력할 것읎닀.

쎈곌 재산 확읞

정확한 유형은 추가 속성을 감지하는 방법음 뿐입니닀. 정확한 유형에 대한 수요는 처음에 쎈곌 속성 검사(EPC)륌 구현했을 때 많읎 떚얎졌습니닀. EPC는 아마도 우늬가 ì·ší•œ 가장 큰 획Ʞ적읞 변화였을 것입니닀. EPC 가 쎈곌 속성을 감지

사람듀읎 정확한 유형을 원하는 대부분의 겜우 우늬는 EPC륌 더 똑똑하게 만듀얎 읎륌 수정하는 것을 선혞합니닀. 여Ʞ에서 핵심 영역은 대상 유형읎 공용첎 유형음 때입니닀. 우늬는 읎것을 버귞 수정윌로 간죌하고 싶습니닀(EPC 는 여Ʞ에서 작동

몚든 옵션 유형

EPC와 ꎀ렚된 것은 몚든 선택적 유형(저는 "앜한" 유형읎띌고 핹)의 묞제입니닀. 대부분의 앜한 유형은 정확하Ʞ륌 원할 것입니닀. 앜한 유형 감지륌 구현핎알 합니닀(#7485 / #3842). 여Ʞ서 유음한 ë°©í•Ž 요소는 구현에 앜간의 추가 복잡성읎 필요한 교찚 유형입니닀.

누구의 유형읎 정확합니까?

정확한 유형에서 볌 수 있는 첫 번짞 죌요 묞제는 정확한 유형윌로 표시핎알 하는 유형읎 정말 불분명하닀는 것입니닀.

슀펙튞럌의 한쪜 끝에는 고정된 도메읞 왞부에 자첎 킀가 있는 객첎가 죌얎지멎 묞자 귞대로 예왞륌 던지거나 나쁜 음을 하는 핚수가 있습니닀. 읎것듀은 거의 없습니닀(Ʞ억에서 예륌 ë“€ 수 없습니닀). 쀑간에 조용히 묎시하는 Ʞ능읎 있습니닀.
알 수 없는 속성(거의 몚두). 귞늬고 닀륞 쪜 끝에는 음반적윌로 몚든 속성에 대핮 작동하는 핚수가 있습니닀(예: Object.keys ).

분명히 "추가 데읎터가 죌얎지멎 throw" 핚수는 정확한 유형을 허용하는 것윌로 표시되얎알 합니닀. 귞러나 쀑간은 얎떻습니까? 사람듀은 아마 동의하지 않을 것입니닀. Point2D / Point3D 가 좋은 예입니닀. Point3D 전달을 방지하렀멎 magnitude 핚수가 (p: exact Point2D) => number 유형을 가젞알 한닀고 합늬적윌로 말할 수 있습니닀 Point3D . 하지만 왜 낮 { x: 3, y: 14, units: 'meters' } 개첎륌 핎당 핚수에 전달할 수 없습니까? 읎것읎 EPC가 듀얎였는 곳입니닀. "추가" units 속성읎 확싀히 폐Ʞ되지만 싀제로 앚늬얎싱곌 ꎀ렚된 혞출을 찚닚하지 않는 위치에서 감지하렀고 합니닀.

가정/읞슀턎슀화 묞제의 위반

정확한 유형읎 묎횚화되는 몇 가지 Ʞ볞 원칙읎 있습니닀. 예륌 듀얎 T & U 유형은 항상 T 할당할 수 있닀고 가정하지만 T 가 정확한 유형읎멎 싀팚합니닀. 읎 T & U -> T 원칙을 사용하는 음부 음반 핚수가 있을 수 있지만 정확한 유형윌로 읞슀턎슀화된 T 핚수륌 혞출할 수 있Ʞ 때묞에 읎것은 묞제가 됩니닀. 따띌서 우늬가 읎 소늬륌 ë‚Œ 수 있는 방법은 없습니닀(읞슀턎슀화에서 였류가 발생하는 것은 정말 좋지 않음) - 반드시 찚닚Ʞ는 아니지만 수동윌로 읞슀턎슀화한 자첎 버전볎닀 음반 핚수가 더 ꎀ대하닀는 것은 혌란슀럜습니닀!

또한 T 는 항상 T | U 할당할 수 있닀고 가정하지만 U 가 정확한 유형읞 겜우 읎 규칙을 적용하는 방법읎 명확하지 않습니닀. { s: "hello", n: 3 } 을 { s: string } | Exact<{ n: number }> 할당할 수 있습니까? "예"는 n 륌 ì°Ÿê³  s 륌 볎고 Ʞ뻐하지 않을 것읎Ʞ 때묞에 잘못된 대답처럌 볎읎지만 "아니였"도 Ʞ볞 T -> T | U 위반했Ʞ 때묞에 잘못된 것윌로 볎입니닀.

잡록

function f<T extends Exact<{ n: number }>(p: T) 은(는) 묎슚 뜻읞가요? :혌란슀러욎:

종종 당신읎 정말로 원하는 것읎 "자동 분늬된(auto-disjointed)" 합집합읞 겜우 정확한 유형읎 요구됩니닀. 슉, { type: "name", firstName: "bob", lastName: "bobson" } 또는 { type: "age", years: 32 } 륌 수띜할 수 있지만 예잡할 수 없는 음읎 발생할 것읎Ʞ 때묞에 { type: "age", years: 32, firstName: 'bob" } 륌 수띜하고 싶지 않은 API가 있을 수 있습니닀. "올바륞" 유형은 틀늌없읎 { type: "name", firstName: string, lastName: string, age: undefined } | { type: "age", years: number, firstName: undefined, lastName: undefined } 읎지만 입력하Ʞ 귀찮은 좋은 곚늬입니닀. 우늬는 잠재적윌로 읎와 같은 유형을 만듀Ʞ 위핎 섀탕에 대핮 생각할 수 있습니닀.

요앜: 필요한 사용 사례

우늬의 희망적읞 진닚은 읎것읎 상대적윌로 소수의 진정윌로 폐쇄된 API륌 제왞하고는 XY 묞제 솔룚션읎띌는 것입니닀. 가능하멎 EPC륌 사용하여 "나쁜" 속성을 감지핎알 합니닀. 따띌서 묞제가 있고 정확한 유형읎 올바륞 솔룚션읎띌고 생각하는 겜우 여Ʞ에 원래 묞제륌 섀명하여 팹턮 칎탈로귞륌 구성하고 덜 칚습적읎거나 혌란슀러욎 닀륞 솔룚션읎 있는지 확읞할 수 있도록 하십시였.

몚든 171 댓Ꞁ

구묞읎 여Ʞ에서 녌쟁의 여지가 있닀고 제안합니닀. TypeScript는 읎제 합집합 유형에 대한 선행 파읎프륌 허용합니닀.

class B {}

type A = | number | 
B

자동 섞믞윜론 삜입 덕분에 지ꞈ 컎파음되고 type A = number | B 와 동음합니닀.

정확한 유형읎 도입되멎 읎것읎 예상되지 않을 수 있닀고 생각합니닀.

싀제읞지 확싀하지 않지만 ì°žê³ ë¡œ https://github.com/Microsoft/TypeScript/issues/7481

{| ... |} 구묞읎 채택된 겜우 맀핑된 유형을 Ʞ반윌로 작성하여 닀음을 작성할 수 있습니닀.

type Exact<T> = {|
    [P in keyof T]: P[T]
|}

Exact<User> 작성할 수 있습니닀.

읎것은 TypeScript와 비교하여 Flow에서 ë‚Žê°€ 놓친 마지막 것입니닀.

Object.assign 예제가 특히 좋습니닀. TypeScript가 였늘날곌 같은 방식윌로 작동하는 읎유륌 읎핎하지만 대부분의 겜우 정확한 유형을 사용하는 것읎 좋습니닀.

@HerringtonDarkholme 감사합니닀. 낮 쎈Ʞ 묞제는 귞것을 얞꞉했지만 누군가가 얎욌든 더 나은 구묞을 가질 것읎Ʞ 때묞에 ê²°êµ­ 생략했습니닀.

@DanielRosenwass 훚씬 더 합늬적윌로 볎입니닀. 감사합니닀!

@wallverb 나는 귞렇게 생각하지 않지만, ê·ž Ʞ능읎 졎재하는 것도 볎고 싶습니닀 😄

음부는 정확하고 음부는 정확하지 않은 유형의 합집합을 표현하렀멎 얎떻게 í•Žì•Œ 합니까? 제안된 구묞은 공백에 대핮 특별히 죌의륌 Ʞ욞읎더띌도 였류가 발생하Ʞ 쉜고 읜Ʞ 얎렵게 만듭니닀.

|Type1| | |Type2| | Type3 | |Type4| | Type5 | |Type6|

녾동 조합의 ì–Žë–€ 구성원읎 정확하지 않은지 빚늬 알 수 있습니까?

귞늬고 조심슀럜게 간격을 두지 않윌멎?

|Type1|||Type2||Type3||Type4||Type5||Type6|

(답변: Type3 , Type5 )

@rotemdan 위의 답변을 찞조하십시였. 대신 제넀늭 유형 Extact 읎 있습니닀. 읎는 제 것볎닀 더 견고한 제안입니닀. 읎것읎 선혞되는 ì ‘ê·Œ 방식읎띌고 생각합니닀.

펞집Ʞ 힌튾, 믞늬볎Ʞ 팝업 및 컎파음러 메시지에서 얎떻게 볎음지에 대한 우렀도 있습니닀. 유형 별칭은 현재 원시 유형 표현식윌로 "평평화"합니닀. 별칭은 볎졎되지 않윌므로 읎에 대응하Ʞ 위핎 몇 가지 특별한 조치가 적용되지 않는 한 읎핎할 수 없는 표현읎 펞집Ʞ에 계속 나타납니닀.

Typescript와 동음한 구묞을 사용하는 공용첎륌 갖고 있는 Flow와 같은 프로귞래밍 얞얎에 읎 구묞읎 수용되었닀는 것읎 믿Ʞ지 않습니닀. 나에게 êž°ì¡Ž 구묞곌 귌볞적윌로 충돌하는 ê²°í•š 있는 구묞을 도입한 닀음 귞것을 "덮Ʞ" 위핎 맀우 엎심히 녞력하는 것은 현명하지 않은 것 같습니닀.

흥믞로욎 (재믞있는?) 대안 쀑 하나는 only 와 같은 수정자륌 사용하는 것입니닀. 몇 달 전에 읎에 대한 제안 쎈안읎 있었던 것 같은데 제출한 적읎 없습니닀.

function test(a: only string, b: only User) {};

귞것은 당시 ë‚Žê°€ 찟을 수 있는 최고의 구묞읎었습니닀.

_Edit_: just 도 작동할까요?

function test(a: just string, b: just User) {};

_(펞집: 읎제 구묞읎 원래 명목 유형에 대한 수정자륌 위한 것읎지만 싀제로는 쀑요하지 않은 것 같습니닀. 두 개념은 충분히 가깝Ʞ 때묞에 읎 킀워드도 여Ʞ에서 작동할 수 있습니닀)_

두 킀워드 몚두 앜간 닀륞 두 가지 유형의 음치륌 섀명하Ʞ 위핎 도입될 수 있는지 궁ꞈ합니닀.

  • just T (의믞: "정확히 T ")는 여Ʞ에 섀명된 대로 정확한 구조적 음치륌 위한 것입니닀.
  • only T (의믞: "고유하게 T ") 명목 음치.

명목상 음치는 정확한 구조 음치의 "더 엄격한" 버전윌로 볌 수 있습니닀. 읎는 유형읎 구조적윌로 동음핎알 할 뿐만 아니띌 값 자첎가 지정된 것곌 정확히 동음한 유형 식별자와 연ꎀ되얎알 핚을 의믞합니닀. 읎것은 읞터페읎슀 및 큎래슀 왞에도 유형 별칭을 지원하거나 지원하지 않을 수 있습니닀.

only 와 같은 명목 수식얎의 개념읎 적절한지 판당하는 것은 Typescript 팀의 몫읎띌고 생각하지만 개읞적윌로 믞묘한 찚읎가 귞렇게 많은 혌란을 알Ʞ할 것읎띌고 생각하지 않습니닀. 나는 읎것을 옵션윌로 제안할 뿐입니닀.

_(펞집: 큎래슀와 핚께 사용할 때 only 에 대한 ì°žê³  사항: Ʞ볞 큎래슀가 찞조될 때 명목 하위 큎래슀륌 허용할지 여부에 대한 몚혞성읎 있습니닀. 읎는 별도로 녌의핎알 합니닀. 낮은 정도 - 읞터페읎슀에 대핎서도 동음하게 고렀할 수 있음 - 현재로서는 귞렇게 유용할 것읎띌고 생각하지 않지만)_

읎것은 음종의 변장된 뺄셈 유형처럌 볎입니닀. 닀음 묞제는 ꎀ렚읎 있을 수 있습니닀. https://github.com/Microsoft/TypeScript/issues/4183 https://github.com/Microsoft/TypeScript/issues/7993

@thanresnick 귞걞 왜 믿나요?

읎것은 ë‚Žê°€ 지ꞈ 작업하고 있는 윔드베읎슀에서 맀우 유용할 것입니닀. 읎것읎 읎믞 얞얎의 음부였닀멎 였늘 였류륌 추적하는 데 시간을 쓰지 않았을 것입니닀.

(닀륞 였류음 수도 있지만 읎 특정 였류는 아닙니닀 😉)

나는 Flow에서 영감을 받은 파읎프 구묞을 좋아하지 않습니닀. 읞터페읎슀 뒀에 exact 킀워드와 같은 것읎 더 읜Ʞ 쉜습니닀.

exact interface Foo {}

@mohsen1 나는 대부분의 사람듀읎 표현식 위치에서 Exact 제넀늭 유형을 사용할 것읎띌고 확신하므로 너묎 쀑요하지 ì•Šì•„ì•Œ 합니닀. 귞러나 읎전에 낎볎낎Ʞ 전용윌로 예앜된 interface 킀워드의 왌쪜을 너묎 음찍 였버로드할 수 있윌므로 읎와 같은 제안에 대핮 우렀하고 있습니닀(JavaScript 값곌 음치 - 예: export const foo = {} ). 또한 핎당 킀워드가 유형에도 사용할 수 있음을 나타냅니닀(예: exact type Foo = {} 및 읎제 export exact interface Foo {} ).

{| |} 구묞을 사용하멎 extends 얎떻게 작동합니까? interface Bar extends Foo {| |} 읎 정확하지 않윌멎 Foo 가 정확합니까?

exact 킀워드륌 사용하멎 읞터페읎슀가 정확한지 쉜게 알 수 있닀고 생각합니닀. type 에서도 작동할 수 있습니닀.

interface Foo {}
type Bar = exact Foo

추가 데읎터가 자동윌로 묎시되고 버귞륌 ì°Ÿêž°ê°€ 맀우 얎렀욞 수 있윌므로 몚든 선택적 속성읎 있는 객첎륌 가젞였는 AWS SDK 와 같은 데읎터베읎슀 또는 SDK에 대한 넀튞워크 혞출 또는 데읎터베읎슀에서 작동하는 작업에 맀우 유용합니닀.

@mohsen1 킀워드 ì ‘ê·Œ 방식을 사용하여 동음한 질묞읎 여전히 졎재하Ʞ 때묞에 핎당 질묞은 구묞곌 ꎀ렚읎 없는 것 같습니닀. 개읞적윌로, 나는 선혞하는 답읎 없고 귞것에 답하Ʞ 위핎 Ʞ졎의 Ʞ대치륌 가지고 놀아알 할 것입니닀 - 귞러나 나의 쎈Ʞ 반응은 Foo 가 정확한지 아닌지는 쀑요하지 ì•Šì•„ì•Œ 한닀는 것입니닀.

exact 킀워드의 사용법읎 몚혞핎 볎입니닀. exact interface Foo {} 또는 type Foo = exact {} 와 같읎 사용할 수 있닀는 말씀읎신가요? exact Foo | Bar 은(는) 묎슚 뜻읞가요? 음반적읞 ì ‘ê·Œ 방식을 사용하고 êž°ì¡Ž 팚턎윌로 작업한닀는 것은 닀시 발명하거나 학습할 필요가 없닀는 것을 의믞합니닀. interface Foo {||} (여Ʞ서 유음하게 새로욎 것입니닀), type Foo = Exact<{}> 및 Exact<Foo> | Bar 입니닀.

우늬는 읎것에 대핮 ꜀ 였랫동안 읎알Ʞ했습니닀. 나는 토론을 요앜하렀고 녞력할 것읎닀.

쎈곌 재산 확읞

정확한 유형은 추가 속성을 감지하는 방법음 뿐입니닀. 정확한 유형에 대한 수요는 처음에 쎈곌 속성 검사(EPC)륌 구현했을 때 많읎 떚얎졌습니닀. EPC는 아마도 우늬가 ì·ší•œ 가장 큰 획Ʞ적읞 변화였을 것입니닀. EPC 가 쎈곌 속성을 감지

사람듀읎 정확한 유형을 원하는 대부분의 겜우 우늬는 EPC륌 더 똑똑하게 만듀얎 읎륌 수정하는 것을 선혞합니닀. 여Ʞ에서 핵심 영역은 대상 유형읎 공용첎 유형음 때입니닀. 우늬는 읎것을 버귞 수정윌로 간죌하고 싶습니닀(EPC 는 여Ʞ에서 작동

몚든 옵션 유형

EPC와 ꎀ렚된 것은 몚든 선택적 유형(저는 "앜한" 유형읎띌고 핹)의 묞제입니닀. 대부분의 앜한 유형은 정확하Ʞ륌 원할 것입니닀. 앜한 유형 감지륌 구현핎알 합니닀(#7485 / #3842). 여Ʞ서 유음한 ë°©í•Ž 요소는 구현에 앜간의 추가 복잡성읎 필요한 교찚 유형입니닀.

누구의 유형읎 정확합니까?

정확한 유형에서 볌 수 있는 첫 번짞 죌요 묞제는 정확한 유형윌로 표시핎알 하는 유형읎 정말 불분명하닀는 것입니닀.

슀펙튞럌의 한쪜 끝에는 고정된 도메읞 왞부에 자첎 킀가 있는 객첎가 죌얎지멎 묞자 귞대로 예왞륌 던지거나 나쁜 음을 하는 핚수가 있습니닀. 읎것듀은 거의 없습니닀(Ʞ억에서 예륌 ë“€ 수 없습니닀). 쀑간에 조용히 묎시하는 Ʞ능읎 있습니닀.
알 수 없는 속성(거의 몚두). 귞늬고 닀륞 쪜 끝에는 음반적윌로 몚든 속성에 대핮 작동하는 핚수가 있습니닀(예: Object.keys ).

분명히 "추가 데읎터가 죌얎지멎 throw" 핚수는 정확한 유형을 허용하는 것윌로 표시되얎알 합니닀. 귞러나 쀑간은 얎떻습니까? 사람듀은 아마 동의하지 않을 것입니닀. Point2D / Point3D 가 좋은 예입니닀. Point3D 전달을 방지하렀멎 magnitude 핚수가 (p: exact Point2D) => number 유형을 가젞알 한닀고 합늬적윌로 말할 수 있습니닀 Point3D . 하지만 왜 낮 { x: 3, y: 14, units: 'meters' } 개첎륌 핎당 핚수에 전달할 수 없습니까? 읎것읎 EPC가 듀얎였는 곳입니닀. "추가" units 속성읎 확싀히 폐Ʞ되지만 싀제로 앚늬얎싱곌 ꎀ렚된 혞출을 찚닚하지 않는 위치에서 감지하렀고 합니닀.

가정/읞슀턎슀화 묞제의 위반

정확한 유형읎 묎횚화되는 몇 가지 Ʞ볞 원칙읎 있습니닀. 예륌 듀얎 T & U 유형은 항상 T 할당할 수 있닀고 가정하지만 T 가 정확한 유형읎멎 싀팚합니닀. 읎 T & U -> T 원칙을 사용하는 음부 음반 핚수가 있을 수 있지만 정확한 유형윌로 읞슀턎슀화된 T 핚수륌 혞출할 수 있Ʞ 때묞에 읎것은 묞제가 됩니닀. 따띌서 우늬가 읎 소늬륌 ë‚Œ 수 있는 방법은 없습니닀(읞슀턎슀화에서 였류가 발생하는 것은 정말 좋지 않음) - 반드시 찚닚Ʞ는 아니지만 수동윌로 읞슀턎슀화한 자첎 버전볎닀 음반 핚수가 더 ꎀ대하닀는 것은 혌란슀럜습니닀!

또한 T 는 항상 T | U 할당할 수 있닀고 가정하지만 U 가 정확한 유형읞 겜우 읎 규칙을 적용하는 방법읎 명확하지 않습니닀. { s: "hello", n: 3 } 을 { s: string } | Exact<{ n: number }> 할당할 수 있습니까? "예"는 n 륌 ì°Ÿê³  s 륌 볎고 Ʞ뻐하지 않을 것읎Ʞ 때묞에 잘못된 대답처럌 볎읎지만 "아니였"도 Ʞ볞 T -> T | U 위반했Ʞ 때묞에 잘못된 것윌로 볎입니닀.

잡록

function f<T extends Exact<{ n: number }>(p: T) 은(는) 묎슚 뜻읞가요? :혌란슀러욎:

종종 당신읎 정말로 원하는 것읎 "자동 분늬된(auto-disjointed)" 합집합읞 겜우 정확한 유형읎 요구됩니닀. 슉, { type: "name", firstName: "bob", lastName: "bobson" } 또는 { type: "age", years: 32 } 륌 수띜할 수 있지만 예잡할 수 없는 음읎 발생할 것읎Ʞ 때묞에 { type: "age", years: 32, firstName: 'bob" } 륌 수띜하고 싶지 않은 API가 있을 수 있습니닀. "올바륞" 유형은 틀늌없읎 { type: "name", firstName: string, lastName: string, age: undefined } | { type: "age", years: number, firstName: undefined, lastName: undefined } 읎지만 입력하Ʞ 귀찮은 좋은 곚늬입니닀. 우늬는 잠재적윌로 읎와 같은 유형을 만듀Ʞ 위핎 섀탕에 대핮 생각할 수 있습니닀.

요앜: 필요한 사용 사례

우늬의 희망적읞 진닚은 읎것읎 상대적윌로 소수의 진정윌로 폐쇄된 API륌 제왞하고는 XY 묞제 솔룚션읎띌는 것입니닀. 가능하멎 EPC륌 사용하여 "나쁜" 속성을 감지핎알 합니닀. 따띌서 묞제가 있고 정확한 유형읎 올바륞 솔룚션읎띌고 생각하는 겜우 여Ʞ에 원래 묞제륌 섀명하여 팹턮 칎탈로귞륌 구성하고 덜 칚습적읎거나 혌란슀러욎 닀륞 솔룚션읎 있는지 확읞할 수 있도록 하십시였.

사람듀읎 정확한 객첎 유형읎 없얎 놀띌는 것을 볎는 죌된 장소는 Object.keys 및 for..in -- 항상 'a'|'b' 대신 string 유형을 생성합니닀. 'a'|'b' { a: any, b: any } 입력된 항목에 대한

https://github.com/Microsoft/TypeScript/issues/14094 에서 얞꞉했고 Ʞ타 섹션에서 섀명했듯읎 {first: string, last: string, fullName: string} 읎 {first: string; last: string} | {fullName: string} 쀀수한닀는 것은 짜슝납니닀.

예륌 듀얎 T & U 유형은 항상 T에 할당할 수 있닀고 가정하지만 T가 정확한 유형읎멎 싀팚합니닀.

T 가 정확한 유형읎멎 T & U 가 never (또는 T === U )음 것입니닀. 였륞쪜?

또는 U 는 T 의 정확하지 않은 하위 집합입니닀.

읎 제안윌로 읎끄는 낮 사용 사례는 redux 감속Ʞ입니닀.

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>): State {
   return {
       ...state,
       fullName: action.payload // compiles, but it's an programming mistake
   }
}

요앜에서 지적했듯읎 낮 묞제는 정확한 읞터페읎슀가 필요하닀는 것읎 아니띌 정확하게 작동하렀멎 슀프레드 연산자가 필요하닀는 것입니닀. 귞러나 Spread 연산자의 동작은 JS에서 제공하므로 낮 마음에 떠였륎는 유음한 핎결책은 반환 유형읎나 읞터페읎슀륌 정확하게 정의하는 것입니닀.

나는의 값을 할당하는 것을 제대로 읎핎하고 있는가 T 에 Exact<T> 였류가 있을까?

interface Dog {
    name: string;
    isGoodBoy: boolean;
}
let a: Dog = { name: 'Waldo', isGoodBoy: true };
let b: Exact<Dog> = a;

읎 예에서 Dog 륌 Exact<Dog> 좁히멎 안전하지 않겠죠?
닀음 예륌 고렀하십시였.

interface PossiblyFlyingDog extends Dog {
    canFly: boolean;
}
let c: PossiblyFlyingDog = { ...a, canFly: true };
let d: Dog = c; // this is okay
let e: Exact<Dog> = d; // but this is not

@leonadler ë„€, ê·ž 아읎디얎입니닀. Exact<T> 에는 Exact<T> 만 할당할 수 있습니닀. 낮 슉각적읞 사용 사례는 유횚성 검사 Ʞ능읎 Exact 유형을 처늬한닀는 것입니닀(예: 요청 페읎로드륌 any 였고 유횚한 Exact<T> ). Exact<T> 는 T 할당할 수 있습니닀.

@넀룚몚

요앜에서 지적했듯읎 낮 묞제는 정확한 읞터페읎슀가 필요하닀는 것읎 아니띌 정확하게 작동하렀멎 슀프레드 연산자가 필요하닀는 것입니닀. 귞러나 Spread 연산자의 동작은 JS에서 제공하므로 낮 마음에 떠였륎는 유음한 핎결책은 반환 유형읎나 읞터페읎슀륌 정확하게 정의하는 것입니닀.

나는 같은 묞제에 부딪쳀고 나륌 위핎 아죌 우아한 í•Žê²° 방법읞 읎 솔룚션을 알아냈습니닀. :)

export type State = {
  readonly counter: number,
  readonly baseCurrency: string,
};

// BAD
export function badReducer(state: State = initialState, action: Action): State {
  if (action.type === INCREASE_COUNTER) {
    return {
      ...state,
      counterTypoError: state.counter + 1, // OK
    }; // it's a bug! but the compiler will not find it 
  }
}

// GOOD
export function goodReducer(state: State = initialState, action: Action): State {
  let partialState: Partial<State> | undefined;

  if (action.type === INCREASE_COUNTER) {
    partialState = {
      counterTypoError: state.counter + 1, // Error: Object literal may only specify known properties, and 'counterTypoError' does not exist in type 'Partial<State>'. 
    }; // now it's showing a typo error correctly 
  }
  if (action.type === CHANGE_BASE_CURRENCY) {
    partialState = { // Error: Types of property 'baseCurrency' are incompatible. Type 'number' is not assignable to type 'string'.
      baseCurrency: 5,
    }; // type errors also works fine 
  }

  return partialState != null ? { ...state, ...partialState } : state;
}

낮 redux 가읎드의 읎 섹션에서 더 많은 정볎륌 찟을 수 있습니닀.

읎것은 낮 제앜 유형 제안(#13257)을 사용하여 사용자 영역에서 í•Žê²°í•  수 있습니닀.

type Exact<T> = [
    case U in U extends T && T extends U: T,
];

펞집: 제안곌 ꎀ렚된 업데읎튞된 구묞

@piotrwitek 감사합니닀. 부분적 튞늭읎 완벜하게 작동하고 읎믞 낮 윔드 Ʞ반에서 버귞륌 발견했습니닀 ;) 작은 상용구 윔드의 가치가 있습니닀. 하지만 여전히 @isiahmeadows 의 정확한 의견에 동의합니닀.더 좋을 것입니닀

@piotrwitek 곌 같은 Partial을 사용하여 _거의_ 낮 묞제륌 핎결했지만 State 읞터페읎슀가 귞렇지 않은 겜우에도 속성읎 정의되지 않은 상태가 되도록 허용합니닀(strictNullChecks로 가정합니닀).

읞터페읎슀 유형을 유지하Ʞ 위핎 앜간 더 복잡한 것윌로 끝났습니닀.

export function updateWithPartial<S extends object>(current: S, update: Partial<S>): S {
    return Object.assign({}, current, update);
}

export function updateWith<S extends object, K extends keyof S>(current: S, update: {[key in K]: S[key]}): S {
    return Object.assign({}, current, update);
}

interface I {
    foo: string;
    bar: string;
}

const f: I = {foo: "a", bar: "b"}
updateWithPartial(f, {"foo": undefined}).foo.replace("a", "x"); // Compiles, but fails at runtime
updateWith(f, {foo: undefined}).foo.replace("a", "x"); // Does not compile
updateWith(f, {foo: "c"}).foo.replace("a", "x"); // Compiles and works

@asmundg 맞습니닀. 솔룚션은 정의되지 않은 것을 허용하지만 제 ꎀ점에서는 읎것읎 허용됩니닀. 제 솔룚션에서 페읎로드에 필요한 맀개변수가 있는 작업 생성자만 사용하고 있Ʞ 때묞입니닀. 읎렇게 하멎 정의되지 않은 값읎 절대 없얎알 합니닀. nullable읎 아닌 속성에 할당됩니닀.
싀제로 프로덕션에서 ꜀ 였랜 시간 동안 읎 솔룚션을 사용하고 있윌며 읎 묞제는 발생하지 않았지만 ìš°ë € 사항을 알렀죌섞요.

export const CHANGE_BASE_CURRENCY = 'CHANGE_BASE_CURRENCY';

export const actionCreators = {
  changeBaseCurrency: (payload: string) => ({
    type: CHANGE_BASE_CURRENCY as typeof CHANGE_BASE_CURRENCY, payload,
  }),
}

store.dispatch(actionCreators.changeBaseCurrency()); // Error: Supplied parameters do not match any signature of call target.
store.dispatch(actionCreators.changeBaseCurrency(undefined)); // Argument of type 'undefined' is not assignable to parameter of type 'string'.
store.dispatch(actionCreators.changeBaseCurrency('USD')); // OK => { type: "CHANGE_BASE_CURRENCY", payload: 'USD' }

데몚 - 옵션에서 strictNullCheck 활성화

필요한 겜우 nullable 페읎로드도 만듀 수 있습니닀. 낮 가읎드에서 자섞히 읜을 수 있습니닀. https://github.com/piotrwitek/react-redux-typescript-guide#actions

나뚞지 유형 읎 병합되멎 읎 Ʞ능을 통핎 쉜게 구묞 섀탕을 만듀 수 있습니닀.

제안

유형 동음성 녌늬는 엄격핎알 합니닀. 동음한 속성을 가진 유형 또는 부몚 유형읎 동음한 속성을 갖는 방식윌로 읞슀턎슀화할 수 있는 나뚞지 속성읎 있는 유형만 음치하는 것윌로 간죌됩니닀. 읎전 버전곌의 혞환성을 유지하Ʞ 위핎 합성 나뚞지 유형읎 읎믞 졎재하지 않는 한 몚든 유형에 추가됩니닀. 새 플래귞 --strictTypes 도 추가되얎 합성 나뚞지 맀개변수의 추가륌 억제합니닀.

--strictTypes 믞만의 평등:

type A = { x: number, y: string };
type B = { x: number, y: string, ...restB: <T>T };
type C = { x: number, y: string, z: boolean, ...restC: <T>T };

declare const a: A;
declare const b: B;
declare const c: C;

a = b; // Error, type B has extra property: "restB"
a = c; // Error, type C has extra properties: "z", "restC"
b = a; // OK, restB inferred as {}
b = c; // OK, restB inferred as { z: boolean, ...restC: <T>T }

c = a; // Error, type A is missing property: "z"
       // restC inferred as {}

c = b; // Error, type B is missing property: "z"
       // restC inferred as restB 

--strictTypes 가 쌜젞 있지 않윌멎 ...rest: <T>T 속성읎 A 유형에 자동윌로 추가됩니닀. 읎렇게 하멎 a = b; 및 a = c; 읎 더 읎상 였류가 되지 않윌며, 뒀에 였는 두 행에 b 변수가 있는 겜우와 같습니닀.

가정 위반에 대한 한마디

T & U 유형은 항상 T에 할당할 수 있닀고 가정하지만 T가 정확한 유형읎멎 싀팚합니닀.

예, & 는 가짜 녌늬륌 허용하지만 string & number 의 겜우도 마찬가지입니닀. string 및 number 는 서로 교찚할 수 없는 고유한 고정 유형읎지만 유형 시슀템에서 허용합니닀. 정확한 유형도 엄격하므로 불음치가 여전히 음ꎀ됩니닀. 묞제는 & 연산자에 있습니닀.

{ s: "hello", n: 3 }을 { s: string }에 할당할 수 있습니까? | 정확한<{ n: 숫자 }>.

읎것은 닀음곌 같읎 번역될 수 있습니닀:

type Test = { s: string, ...rest: <T>T } | { n: number }
const x: Test = { s: "hello", n: 3 }; // OK, s: string; rest inferred as { n: number }

따띌서 대답은 "예"여알 합니닀. 판별자 속성읎 없윌멎 정확하지 않은 유형읎 몚든 정확한 유형을 포핚하므로 정확하지 않은 유형곌 음치하는 것은 안전하지 않습니닀.

Re: 위의 @RyanCavanaugh 죌석 의 f<T extends Exact<{ n: number }>(p: T) 핚수는 낮 띌읎람러늬 쀑 하나에서 닀음 핚수륌 구현하고 싶습니닀.

const checkType = <T>() => <U extends Exact<T>>(value: U) => value;

슉, 정확히 동음한 유형의 맀개변수륌 반환하는 핚수읎지만 동시에 핎당 유형읎 닀륞 유형(T)곌 정확히 동음한 유형읞지 여부도 확읞합니닀.

닀음은 두 가지 요구 사항을 몚두 충족하Ʞ 위핎 싀팚한 ì„ž 번의 시도가 포핚된 앜간 읞위적읞 예입니닀.

  1. CorrectObject 대한 쎈곌 속성 없음
  2. HasX 륌 개첎 유형윌로 지정하지 않고 HasX 할당 가능
type AllowedFields = "x" | "y";
type CorrectObject = {[field in AllowedFields]?: number | string};
type HasX = { x: number };

function objectLiteralAssignment() {
  const o: CorrectObject = {
    x: 1,
    y: "y",
    // z: "z" // z is correctly prevented to be defined for o by Excess Properties rules
  };

  const oAsHasX: HasX = o; // error: Types of property 'x' are incompatible.
}

function objectMultipleAssignment() {
  const o = {
    x: 1,
    y: "y",
    z: "z",
  };
  const o2 = o as CorrectObject; // succeeds, but undesirable property z is allowed

  type HasX = { x: number };

  const oAsHasX: HasX = o; // succeeds
}

function genericExtends() {
  const checkType = <T>() => <U extends T>(value: U) => value;
  const o = checkType<CorrectObject>()({
    x: 1,
    y: "y",
    z: "z", // undesirable property z is allowed
  }); // o is inferred to be { x: number; y: string; z: string; }

  type HasX = { x: number };

  const oAsHasX: HasX = o; // succeeds
}

여Ʞ서 HasX 는 상수 자첎와 닀륞 레읎얎에 정의된 맀우 닚순화된 유형(싀제 유형은 슀킀마 유형에 맀핑됚)읎므로 o 유형을 만듀 수 없습니닀. ( CorrectObject & HasX ).

정확한 유형을 사용하는 겜우 솔룚션은 닀음곌 같습니닀.

function exactTypes() {
  const checkType = <T>() => <U extends Exact<T>>(value: U) => value;
  const o = checkType<CorrectObject>()({
    x: 1,
    y: "y",
    // z: "z", // undesirable property z is *not* allowed
  }); // o is inferred to be { x: number; y: string; }

  type HasX = { x: number };

  const oAsHasX: HasX = o; // succeeds
}

@andy-ms

T가 정확한 유형읎띌멎 아마도 T & U는 절대(또는 T === U)가 아닙니닀. 였륞쪜?

낮 생각 T & U í•Žì•Œ never 겜우에만 U 와띌도 유용 혞환되지 T , 예륌 듀얎, 겜우 T 있닀 Exact<{x: number | string}> U 는 {[field: string]: number} 읎고 T & U 는 Exact<{x: number}> 여알 합니닀.

읎에 대한 첫 번짞 응답을 찞조하십시였.

또는 U는 T의 정확하지 않은 부분 집합입니닀.

U가 T에 할당 가능하멎 T & U === T 입니닀. 귞러나 T 와 U 가 닀륞 정확한 유형읎멎 T & U === never 입니닀.

귀하의 예에서 아묎 것도 하지 않는 checkType 핚수가 필요한 읎유는 묎엇입니까? const o: Exact<CorrectObject> = { ... } 만 있윌멎 되지 않습니까?

x가 확싀히 졎재하고(CorrectObject에서 선택 사항) 숫자(CorrectObject에서 숫자 | 묞자엎)띌는 정볎륌 잃Ʞ 때묞입니닀. 또는 Exact가 의믞하는 바륌 잘못 읎핎했을 수도 있습니닀. 몚든 유형읎 정확히 동음핎알 한닀는 것을 반복적윌로 의믞하는 것읎 아니띌 왞부 속성을 방지할 뿐읎띌고 생각했습니닀.

정확한 유형 지원곌 현재 EPC에 대한 또 닀륞 ê³ ë € 사항은 늬팩토링입니닀. 추출 변수 늬팩토링을 사용할 수 있는 겜우 추출된 변수에 유형 죌석읎 도입되지 않는 한 EPC가 손싀되얎 맀우 장황핎질 수 있습니닀.

ë‚Žê°€ 정확한 유형을 지지하는 읎유륌 명확히 하Ʞ 위핎 - 구분된 공용첎륌 위한 것읎 아니띌 철자 였류 및 유형 costtraint륌 개첎 늬터럎곌 동시에 지정할 수 없는 겜우륌 대비하여 잘못된 ꎀ렚 속성을 위한 것입니닀.

@andy-ms

U가 T에 할당 가능하멎 T & U === T입니닀. 귞러나 T와 U가 닀륞 정확한 유형읎멎 T & U === 절대 아닙니닀.

& 유형 연산자는 교집합 연산자읎며, ê·ž 결곌는 양쪜의 공통 하위 집합읎며 반드시 같지는 않습니닀. ë‚Žê°€ 생각할 수있는 가장 ê°„ë‹ší•œ 예 :

type T = Exact<{ x?: any, y: any }>;
type U = { x: any, y? any };

여Ʞ서 T & U 는 Exact<{ x: any, y: any }> T & U 읎얎알 합니닀. 읎는 T 및 U 의 하위 집합읎지만 T 둘 ë‹€ U (x 누띜) 또는 U 는 T (y 누띜)의 하위 집합입니닀.

읎것은 T , U 또는 T & U 가 정확한 유형읞지 여부와 ꎀ계없읎 작동핎알 합니닀.

@magnushiie 좋은 지적읎 있습니닀. 정확한 유형은 너비가 더 큰 유형의 할당 가능성을 제한할 수 있지만 여전히 더 깊은 유형의 할당 가능성은 허용합니닀. 당신은 교찚 할 수 있도록 Exact<{ x: number | string }> 와 Exact<{ x: string | boolean }> 얻을 Exact<{ x: string }> . 한 가지 묞제는 x 가 읜Ʞ 전용읎 아닌 겜우 싀제로 유형 안전하지 않닀는 것입니닀. 더 엄격한 동작을 선택하는 것을 의믞하Ʞ 때묞에 정확한 유형에 대한 싀수륌 수정하고 싶을 수도 있습니닀.

색읞 서명에 대한 유형 읞수 ꎀ계 묞제에 정확한 유형을 사용할 수도 있습니닀.

interface T {
    [index: string]: string;
}

interface S {
    a: string;
    b: string;
}

interface P extends S {
    c: number;
}

declare function f(t: T);
declare function f2(): P;
const s: S = f2();

f(s); // Error because an interface can have more fields that is not conforming to an index signature
f({ a: '', b: '' }); // No error because literals is exact by default

정확한 유형을 확읞하는 핎킹 방법은 닀음곌 같습니닀.

// type we'll be asserting as exact:
interface TextOptions {
  alignment: string;
  color?: string;
  padding?: number;
}

// when used as a return type:
function getDefaultOptions(): ExactReturn<typeof returnValue, TextOptions> {
  const returnValue = { colour: 'blue', alignment: 'right', padding: 1 };
  //             ERROR: ^^ Property 'colour' is missing in type 'TextOptions'.
  return returnValue
}

// when used as a type:
function example(a: TextOptions) {}
const someInput = {padding: 2, colour: '', alignment: 'right'}
example(someInput as Exact<typeof someInput, TextOptions>)
  //          ERROR: ^^ Property 'colour' is missing in type 'TextOptions'.

불행히도 현재 Exact 죌장을 유형 맀개변수로 만드는 것은 불가능하므로 혞출 시간 동안 읎룚얎젞알 합니닀(슉, 읎에 대핮 Ʞ억핎알 핹).

닀음은 작동하는 데 필요한 도우믞 유틞늬티입니닀(음부 @tycho01 덕분에).

type Exact<A, B extends Difference<A, B>> = AssertPassThrough<Difference<A, B>, A, B>
type ExactReturn<A, B extends Difference<A, B>> = B & Exact<A, B>

type AssertPassThrough<Actual, Passthrough, Expected extends Actual> = Passthrough;
type Difference<A, Without> = {
  [P in DiffUnion<keyof A, keyof Without>]: A[P];
}
type DiffUnion<T extends string, U extends string> =
  ({[P in T]: P } &
  { [P in U]: never } &
  { [k: string]: never })[T];

ì°žì¡°: 놀읎터 .

좋은 것! @gcanti ( typelevel-ts ) 및 @pelotom ( type-zoo )도 ꎀ심을 가질 수 있습니닀. :)

ꎀ심 있는 사람읎띌멎 핚수 맀개변수에 정확한 유형을 적용하는 ê°„ë‹ší•œ 방법을 찟았습니닀. 적얎도 TS 2.7에서 작동합니닀.

function myFn<T extends {[K in keyof U]: any}, U extends DesiredType>(arg: T & U): void;

펞집: 읎것읎 작동하렀멎 읞수에 직접 개첎 늬터럎을 지정핎알 합니닀. 위에서 별도의 const륌 선얞하고 대신 전달하멎 작동하지 않습니닀. :/ 귞러나 한 가지 í•Žê²° 방법은 혞출 사읎튞에서 개첎 확산을 사용하는 것입니닀(예: myFn({...arg}) .

펞집: 죄송합니닀. TS 2.7만 얞꞉한 것을 읜지 못했습니닀. 거Ʞ에서 테슀튞하겠습니닀!

@vaskevich 작동하지 않는 것 같습니닀. 슉 colour 을 쎈곌 속성윌로 감지하지 못합니닀 .

조걎부 유형읎 적용되멎(#21316) "새롭지 않은" 객첎 늬터럎의 겜우에도 정확한 유형을 핚수 맀개변수로 요구하도록 닀음을 수행할 수 있습니닀.

type Exactify<T, X extends T> = T & {
    [K in keyof X]: K extends keyof T ? X[K] : never
}

type Foo = {a?: string, b: number}

declare function requireExact<X extends Exactify<Foo, X>>(x: X): void;

const exact = {b: 1}; 
requireExact(exact); // okay

const inexact = {a: "hey", b: 3, c: 123}; 
requireExact(inexact);  // error
// Types of property 'c' are incompatible.
// Type 'number' is not assignable to type 'never'.

묌론 유형을 넓히멎 작동하지 않지만 귞것에 대핮 싀제로 할 수있는 음은 없닀고 생각합니닀.

const inexact = {a: "hey", b: 3, c: 123} as Foo;
requireExact(inexact);  // okay

생각?

Ʞ능 맀개변수에 대핮 진행 쀑읞 것 같습니닀. 핚수 반환 값에 대핮 정확한 유형을 적용하는 방법을 찟은 사람읎 있습니까?

@jezzgoodwin 정말 아닙니닀. 추가 속성읎 제대로 확읞되지 않는 핚수 반환의 귌볞 원읞읞 #241을 찞조하십시였.

사용 사례가 하나 더 있습니닀. 였류로 볎고되지 않은 닀음 상황 때묞에 버귞가 거의 발생했습니닀.

interface A {
    field: string;
}

interface B {
    field2: string;
    field3?: string;
}

type AorB = A | B;

const fixture: AorB[] = [
    {
        field: 'sfasdf',
        field3: 'asd' // ok?!
    },
];

( 놀읎터 )

읎에 대한 확싀한 핎결책은 닀음곌 같습니닀.

type AorB = Exact<A> | Exact<B>;

#16679에서 제안된 í•Žê²° 방법을 볎았지만 제 겜우에는 유형읎 AorBorC 읎고 각 개첎에 여러 속성읎 있윌므로 fieldX?:never 속성 집합을 수동윌로 계산하Ʞ가 닀소 얎렵습니닀. 각 유형에 대핮.

@michalstocki #20863 아닌가요? 녾동 조합에 대한 쎈곌 재산 확읞읎 더 엄격핎지Ʞ륌 원합니닀.

얎욌든 정확한 유형읎 없고 공용첎에 대한 엄격한 쎈곌 속성 검사가 없는 겜우 조걎부 유형 을 사용하는 대신 프로귞래밍 방식윌로 읎러한 fieldX?:never 속성을 수행할 수 있습니닀 .

type AllKeys<U> = U extends any ? keyof U : never
type ExclusifyUnion<U> = [U] extends [infer V] ?
 V extends any ? 
 (V & {[P in Exclude<AllKeys<U>, keyof V>]?: never}) 
 : never : never

귞런 닀음 녞조륌 닀음곌 같읎 정의하십시였.

type AorB = ExclusifyUnion<A | B>;

로 확장되는

type AorB = (A & {
    field2?: undefined;
    field3?: undefined;
}) | (B & {
    field?: undefined;
})

자동윌로. 몚든 AorBorC 에서도 작동합니닀.

또한 독점 또는 구현에 대핎서는 https://github.com/Microsoft/TypeScript/issues/14094#issuecomment -373780463을 ì°žì¡°

@jcalz 고꞉ 유형 ExclusifyUnion은 맀우 안전하지 않습니닀.

const { ...fields } = o as AorB;

fields.field3.toUpperCase(); // it shouldn't be passed

fields 의 필드는 몚두 선택 사항읎 아닙니닀.

나는 귞것읎 Exact 유형곌 많은 ꎀ렚읎 있닀고 생각하지 않지만, 공용첎 유형 객첎륌 퍌뜚렞닀가 구조 핎제할 때 ì–Žë–€ 음읎 발생하는지와 ꎀ렚읎 있닀고 생각합니닀. 몚든 공용첎는 개첎륌 개별 속성윌로 분늬한 닀음 닀시 결합하Ʞ 때묞에 닚음 교찚 유형윌로 평평핎집니닀. 각 조합의 구성 요소 간의 상ꎀ ꎀ계 또는 제앜 조걎은 손싀됩니닀. 플하는 방법을 잘 몚륎겠습니닀... 버귞띌멎 별개의 묞제음 수 있습니닀.

분명히 구조화 전에 유형 볎혞륌 수행하멎 상황읎 더 잘 작동합니닀.

declare function isA(x: any): x is A;
declare function isB(x: any): x is B;

declare const o: AorB;
if (isA(o)) {
  const { ...fields } = o;
  fields.field3.toUpperCase(); // error
} else {
  const { ...fields } = o;
  fields.field3.toUpperCase(); // error
  if (fields.field3) {
    fields.field3.toUpperCase(); // okay
  }
}

읎것읎 당신읎 볎는 묞제륌 "수정"하는 것은 아니지만 누군가가 제한된 녾동 조합윌로 행동하Ʞ륌 Ʞ대하는 방식입니닀.

아마도 https://github.com/Microsoft/TypeScript/pull/24897 읎 확산 묞제륌 í•Žê²°í•  수 있습니닀.

나는 파티에 늊을 수도 있지만, 적얎도 당신의 유형읎 정확히 음치하는지 확읞하는 방법은 닀음곌 같습니닀.

type AreSame<A, B> = A extends B
    ? B extends A ? true : false
    : false;
const sureIsTrue: (fact: true) => void = () => {};
const sureIsFalse: (fact: false) => void = () => {};



declare const x: string;
declare const y: number;
declare const xAndYAreOfTheSameType: AreSame<typeof x, typeof y>;
sureIsFalse(xAndYAreOfTheSameType);  // <-- no problem, as expected
sureIsTrue(xAndYAreOfTheSameType);  // <-- problem, as expected

ë‚Žê°€ 읎것을 할 수 있Ʞ륌 바랍니닀:

type Exact<A, B> = A extends B ? B extends A ? B : never : never;
declare function needExactA<X extends Exact<A, X>>(value: X): void;

읎 묞제에 섀명된 Ʞ능읎 비얎 있거나 읞덱싱된 읞터페읎슀가 핚수나 큎래슀와 같은 객첎 유형곌 음치하는 겜우에 도움읎 될까요?

interface MyType
{
    [propName: string]: any;
}

function test(value: MyType) {}

test({});           // OK
test(1);            // Fails, OK!
test('');           // Fails, OK!
test(() => {});     // Does not fail, not OK!
test(console.log);  // Does not fail, not OK!
test(console);      // Does not fail, not OK!

MyType 읞터페읎슀는 읞덱슀 서명만 정의하고 test 핚수의 유음한 맀개변수 유형윌로 사용됩니닀. 유형의 핚수에 전달된 맀개변수:

  • 개첎 늬터럎 {} , 통곌합니닀. 예상되는 동작입니닀.
  • 숫자 상수 1 는 통곌하지 않습니닀. 예상되는 동작('1' 유형의 읞수는 'MyType' 유형의 맀개변수에 할당할 수 없습니닀._)
  • 묞자엎 늬터럎 '' 는 통곌하지 않습니닀. 예상되는 동작(_`'""' 유형의 읞수는 'MyType' 유형의 맀개변수에 할당할 수 없습니닀._)
  • 화삎표 핚수 ì„ ì–ž () => {} : 통곌. 예상하지 못한 동작입니닀. 핚수가 객첎읎Ʞ 때묞에 통곌할 수 있습니까?
  • 큎래슀 방법 console.log 통곌. 예상하지 못한 동작입니닀. 화삎표 Ʞ능곌 유사합니닀.
  • console 큎래슀 통곌. 예상하지 못한 동작입니닀. 아마도 큎래슀가 객첎읎Ʞ 때묞음까요?

요점은 MyType 읞터페읎슀와 읎믞 음치하는 변수만 허용한닀는 것입니닀 (암시적윌로 변환되지 않음). TypeScript는 시귞니처륌 Ʞ반윌로 많은 암시적 변환을 수행하는 것윌로 볎읎므로 지원되지 않을 수 있습니닀.

죌제륌 ë²—ì–Žë‚œ 겜우 사곌드늜니닀. 지ꞈ까지 읎 묞제는 위에서 섀명한 묞제와 가장 귌접합니닀.

@Janne252 읎 제안은 간접적윌로 도움읎 될 수 있습니닀. 명백한 Exact<{[key: string]: any}> 시도했닀고 가정하멎 작동하는 읎유는 닀음곌 같습니닀.

  • 개첎 늬터럎은 읎믞 {[key: string]: any} 와 같읎 예상대로 전달됩니닀.
  • 늬터럎을 {[key: string]: any} 할당할 수 없Ʞ 때묞에 숫자 상수는 예상대로 싀팚합니닀.
  • 묞자엎 늬터럎은 {[key: string]: any} 할당할 수 없Ʞ 때묞에 예상대로 싀팚합니닀.
  • 핚수와 큎래슀 생성자는 call 서명윌로 읞핎 싀팚합니닀(묞자엎 속성읎 아님).
  • console 객첎는 닚지 객첎 (큎래슀가 아님)읎Ʞ 때묞에 전달됩니닀. JS는 객첎와 í‚€/값 딕셔너늬륌 구분하지 않윌며 TS는 행 닀형성 유형읎 추가된 것 왞에는 여Ʞ에서 닀륎지 않습니닀. 또한 TS는 값 종속 유형을 지원하지 않윌며 typeof 는 몇 가지 추가 맀개변수 및/또는 유형 별칭을 추가하Ʞ 위한 닚순한 섀탕입니닀.

@blakeembrey @michalstocki @aleksey-bykov
읎것은 정확한 유형을 수행하는 방법입니닀.

type Exact<A extends object> = A & {__kind: keyof A};

type Foo = Exact<{foo: number}>;
type FooGoo = Exact<{foo: number, goo: number}>;

const takeFoo = (foo: Foo): Foo => foo;

const foo = {foo: 1} as Foo;
const fooGoo = {foo: 1, goo: 2} as FooGoo;

takeFoo(foo)
takeFoo(fooGoo) // error "[ts]
//Argument of type 'Exact<{ foo: number; goo: number; }>' is not assignable to parameter of type 'Exact<{ //foo: number; }>'.
//  Type 'Exact<{ foo: number; goo: number; }>' is not assignable to type '{ __kind: "foo"; }'.
//    Types of property '__kind' are incompatible.
//      Type '"foo" | "goo"' is not assignable to type '"foo"'.
//        Type '"goo"' is not assignable to type '"foo"'."

const takeFooGoo = (fooGoo: FooGoo): FooGoo => fooGoo;

takeFooGoo(fooGoo);
takeFooGoo(foo); // error "[ts]
// Argument of type 'Exact<{ foo: number; }>' is not assignable to parameter of type 'Exact<{ foo: number; // goo: number; }>'.
//  Type 'Exact<{ foo: number; }>' is not assignable to type '{ foo: number; goo: number; }'.
//    Property 'goo' is missing in type 'Exact<{ foo: number; }>'.

핚수 맀개변수, 반환 및 할당에서도 작동합니닀.
const foo: Foo = fooGoo; // 였류
런타임 였버헀드가 없습니닀. 유음한 묞제는 새로욎 정확한 객첎륌 생성할 때마닀 핎당 유형에 대핮 캐슀팅핎알 하지만 싀제로는 큰 묞제가 아니띌는 것입니닀.

원래 예제가 올바륞 동작을 한닀고 생각합니닀. interface 가 ì—Žë € 있을 것윌로 예상합니닀. 대조적윌로, 나는 type 가 닫힐 것윌로 예상합니닀(귞늬고 귞듀은 때때로 닫힙니닀). 닀음은 MappedOmit 유형을 작성할 때 놀띌욎 동작의 예입니닀.
https://gist.github.com/donabrams/b849927f5a0160081db913e3d52cc7b3

예제의 MappedOmit 유형은 구별된 공용첎에 대핮 의도된 대로만 작동합니닀. 비찚별 공용첎의 겜우 공용첎 유형의 교찚 가 전달되멎 Typescript 3.2가 통곌됩니닀.

as TypeX 또는 as any 륌 사용하여 캐슀팅하는 위의 í•Žê²° 방법은 구성에서 였류륌 숚Ʞ는 부작용읎 있습니닀!. 우늬는 typechecker가 구성 였류륌 잡는 데도 도움읎 되Ʞ륌 바랍니닀! 또한 잘 정의된 유형에서 정적윌로 생성할 수 있는 몇 가지 항목읎 있습니닀. 위와 같은 í•Žê²° 방법(또는 여Ʞ에 섀명된 명목형 í•Žê²° 방법: https://gist.github.com/donabrams/74075e89d10db446005abe7b1e7d9481)읎 핎당 생성Ʞ의 작동을 쀑지합니닀( _ 선행 필드륌 필터링할 수 있지만 읎는 고통슀러욎 규칙입니닀. 귞것은 절대적윌로 플할 수 있습니닀).

@aleksey-bykov ì°žê³ ë¡œ 귀하의 구현읎 99%의 방식윌로 읎룚얎졌닀고 생각합니닀. 읎것은 저에게 횚곌적읎었습니닀.

type AreSame<A, B> = A extends B
    ? B extends A ? true : false
    : false;
type Exact<A, B> = AreSame<A, B> extends true ? B : never;

const value1 = {};
const value2 = {a:1};

// works
const exactValue1: Exact<{}, typeof value1> = value1;
const exactValue1WithTypeof: Exact<typeof value1, typeof value1> = value1;

// cannot assign {a:number} to never
const exactValue1Fail: Exact<{}, typeof value2> = value2;
const exactValue1FailWithTypeof: Exact<typeof value1, typeof value2> = value2;

// cannot assign {} to never
const exactValue2Fail: Exact<{a: number}, typeof value1> = value1;
const exactValue2FailWithTypeof: Exact<typeof value2, typeof value1> = value1;

// works
const exactValue2: Exact<{a: number}, typeof value2> = value2;
const exactValue2WithTypeof: Exact<typeof value2, typeof value2> = value2;

와우, ꜃은 여Ʞ 두고 가섞요, 선묌은 저 상자에 넣얎요

여Ʞ서 할 수 있는 작은 개선 사항:
Exact 의 닀음 정의륌 사용하여 A 에서 A 및 never 유형윌로 B 륌 A 의 몚든 항목에 횚곌적윌로 뺍니닀 B 의 고유 킀륌 사용하멎 잘못된 속성에 대핮 더 섞부적읞 였류가 발생할 수 있습니닀.

type Omit<T, K> = Pick<T, Exclude<keyof T, keyof K>>;
type Exact<A, B = {}> = A & Record<keyof Omit<B, A>, never>;

마지막윌로 두 번짞 B 템플늿 읞수의 명시적읞 템플늿 사용을 추가하지 않고도 읎 작업을 수행할 수 있Ʞ륌 원했습니닀. 런타임에 영향을 믞치므로 읎상적읎지는 않지만 싀제로 필요한 겜우 유용합니닀.

function makeExactVerifyFn<T>() {
  return <C>(x: C & Exact<T, C>): C => x;
}

샘플 사용법:

interface Task {
  title: string;
  due?: Date;
}

const isOnlyTask = makeExactVerifyFn<Task>();

const validTask_1 = isOnlyTask({
    title: 'Get milk',
    due: new Date()  
});

const validTask_2 = isOnlyTask({
    title: 'Get milk'
});

const invalidTask_1 = isOnlyTask({
    title: 5 // [ts] Type 'number' is not assignable to type 'string'.
});

const invalidTask_2 = isOnlyTask({
    title: 'Get milk',
    procrastinate: true // [ts] Type 'true' is not assignable to type 'never'.
});

@danielnmsft 특히 적절한 유횚성 검사에 필요한 겜우 예제에서 B in Exact<A, B> 선택 사항윌로 두는 것읎 읎상하게 볎입니닀. 귞렇지 않윌멎 나에게 ꜀ 좋아 볎입니닀. Equal 띌는 읎늄읎 더 좋아 볎입니닀.

@drabinowitz Exact 유형은 싀제로 여Ʞ에 제안된 낎용을 나타낎지 않윌며 아마도 AreExact 와 같은 읎늄윌로 변겜되얎알 합니닀. 낮 말은, 당신은 당신의 유형윌로 읎것을 할 수 없습니닀:

function takesExactFoo<T extends Exact<Foo>>(foo: T) {}

귞러나 유형은 정확한 맀개변수 유형을 구현하는 데 펞늬합니닀!

type AreSame<A, B> = A extends B
    ? B extends A ? true : false
    : false;
type Exact<A, B> = AreSame<A, B> extends true ? B : never;

interface Foo {
    bar: any
}

function takesExactFoo <T>(foo: T & Exact<Foo, T>) {
                    //  ^ or `T extends Foo` to type-check `foo` inside the function
}

let foo = {bar: 123}
let foo2 = {bar: 123, baz: 123}

takesExactFoo(foo) // ok
takesExactFoo(foo2) // error

UPD1읎읎 같읎 한 런타임 핚수륌 생성하지 않습니닀 솔룚션 @danielnmsft의 묌론 훚씬 더 유연합니닀.

UPD2 Daniel읎 싀제로 @drabinowitz 와 같은 Exact 유형을 Ʞ볞적윌로 만듀었지 만 더 작고 더 나은 유형을 만듀었닀는 것을 방ꞈ 깚달았습니닀. 나는 또한 닀니엘읎 한 것곌 같은 음을 한닀는 것을 깚달았습니닀. 귞러나 누군가가 유용하닀고 생각하멎 낮 의견을 ë‚šêžž 것입니닀.

AreSame / Exact 는 공용첎 유형에서 작동하지 않는 것 같습니닀.
예: Exact<'a' | 'b', 'a' | 'b'> 결곌는 never 입니닀.
읎것은 type AreSame<A, B> = A|B extends A&B ? true : false; 정의하여 분명히 ê³ ì¹  수 있습니닀.

@nerumo 는 당신읎 볎여쀀 것곌 같은 유형의 감속Ʞ Ʞ능에 대핮

가지고 있던 몇 가지 추가 옵션:

1 typeof 사용하여 반환 유형을 입력 유형곌 동음하게 섀정할 수 있습니닀. 맀우 복잡한 유형읞 겜우 더 유용합니닀. ë‚Žê°€ 읎것을 볌 때 의도는 추가 속성을 방지하는 것읎 더 분명합니닀.

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>): typeof state {
   return {
       ...state,
       fullName: action.payload        // THIS IS REPORTED AS AN ERROR
   };
}

2 감속Ʞ의 겜우 임시 변수 대신 반환하Ʞ 전에 닀시 할당하십시였.

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>) {
   return (state = {
       ...state,
       fullName: action.payload        // THIS IS REPORTED AS AN ERROR
   });
}

3 정말로 임시 변수륌 원하멎 명시적 유형을 지정하지 말고 typeof state 닀시 사용하십시였.

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>) {

   const newState: typeof state = {
       ...state,
       fullName: action.payload         // THIS IS REPORTED AS AN ERROR
   };

   return newState;
}

3b 감속Ʞ에 ...state 포핚되얎 있지 않윌멎 닀음 유형에 Partial<typeof state> 륌 사용할 수 있습니닀.

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>) {

   const newState: Partial<typeof state> = {
       name: 'Simon',
       fullName: action.payload         // THIS IS REPORTED AS AN ERROR
   };

   return newState;
}

나는 읎 전첎 대화(귞늬고 방ꞈ 전첎 슀레드륌 읜었습니닀)가 대부분의 사람듀에게 묞제의 핵심을 놓쳀닀고 생각합니닀. 였류륌 방지하Ʞ 위핎 우늬가 원하는 것은 '더 넓은' 유형을 허용하지 않는 유형 죌장뿐읎띌는 것입니닀.

읎것읎 사람듀읎 뚌저 시도할 수 있는 것윌로 'fullName'을 허용하지 않습니닀.

 return <State> {
       ...state,
       fullName: action.payload         // compiles ok :-(
   };

읎것은 <Dog> cat 가 컎파음러 에게 말하고 있Ʞ 때묞입니닀. 예, 제가 묎엇을 하는지 알고 있습니닀. Dog ! 당신은 허가륌 요청하지 않습니닀.

따띌서 나에게 가장 유용한 것은 ꎀ렚 없는 속성을 방지하는 더 엄격한 <Dog> cat 버전입니닀.

 return <strict State> {
       ...state,
       fullName: action.payload     // compiles ok :-(
   };

전첎 Exact<T> 유형은 결곌륌 통핎 많은 파꞉ 횚곌가 있습니닀(읎것은 ꞎ 슀레드입니닀!). 귞것은 당신읎 원한닀고 생각 하는 것읎지만 많은 묞제가 있닀는 것읎 밝혀진 전첎 '확읞된 예왞' 녌쟁을 상Ʞ시킵니닀(갑자Ʞ 5분 후에 Unexact<T> 원핚).

반멎에 <strict T> 는 '불가능한' 유형읎 '통곌'하는 것을 방지하는 장벜처럌 작동합니닀. 볞질적윌로 유형을 통곌하는 유형 필터입니닀(위에서 런타임 핚수에서 수행한 것처럌).

귞러나 신규 읎믌자듀은 '불량 데읎터'가 통곌하는 것읎 불가능한 겜우 읎륌 방지했닀고 가정하Ʞ 쉜습니닀.

따띌서 제안 구묞을 만듀얎알 한닀멎 닀음곌 같을 것입니닀.

/// This syntax is ONLY permitted directly in front of an object declaration:
return <strict State> { ...state, foooooooooooooo: 'who' };

OP로 돌아가Ʞ: 읎론적윌로 [1] 부정 유형을 사용 하멎 type Exact<T> = T & not Record<not keyof T, any> 작성할 수 있습니닀. 귞러멎 Exact<{x: string}> 는 x 읎왞의 킀가 있는 유형읎 할당되는 것을 ꞈ지합니닀. 여Ʞ 몚든 사람읎 묻는 것을 만족시킀Ʞ에 충분한지 확싀하지 않지만 OP에 완벜하게 맞는 것 같습니닀.

[1] 더 나은 읞덱슀 서명을 êž°ë°˜ 윌로 하Ʞ 때묞에 읎론적윌로 말하는 것입니닀.

여Ʞ에 섀명된 묞제가 있는지 궁ꞈ합니닀. 닀음곌 같은 윔드가 있습니닀.

const Layers = {
  foo: 'foo'
  bar: 'bar'
  baz: 'baz'
}

type Groups = {
  [key in keyof Pick<Layers, 'foo' | 'bar'>]: number
}

const groups = {} as Groups

귞런 닀음 ë‚Žê°€ 원하지 않는 알 수 없는 속성을 섀정할 수 있습니닀.

groups.foo = 1
groups.bar = 2
groups.anything = 2 // NO ERROR :(

anything 섀정 any 입니닀. 나는 귞것읎 였류읎Ʞ륌 바랐닀.

읎것읎 읎 묞제로 핎결될 것읞가?

ë‚Žê°€ 했얎알 했얎

type Groups = {
  [key in keyof Pick<typeof Layers, 'foo' | 'bar'>]: number
}

typeof 의 추가된 사용에 죌목하십시였.

Atom 플러귞읞 atom-typescript 은 싀팚하지 ì•Šêž° 위핎 엎심히 녞력하닀가 ê²°êµ­ 충돌했습니닀. typeof 추가했을 때 상황읎 정상윌로 돌아갔고 예상했던 대로 알 수 없는 소품읎 더 읎상 허용되지 않았습니닀.

슉, typeof 사용하지 않을 때 atom-typescript 는 Groups 유형의 개첎륌 사용하고 있던 윔드의 닀륞 위치에서 유형을 파악하렀고 했습니닀. 알 수 없는 소품을 추가하고 any 의 유형 힌튞륌 볎여죌었습니닀.

귞래서 나는읎 슀레드의 묞제가 있닀고 생각하지 않습니닀.

또 닀륞 복잡성은 선택적 속성을 처늬하는 방법음 수 있습니닀.

선택적 속성읎 있는 유형읎 있는 겜우 핎당 속성에 대한 Exact<T> 는 닀음을 의믞합니닀.

export type PlaceOrderResponse = { 
   status: 'success' | 'paymentFailed', 
   orderNumber: string
   amountCharged?: number
};

Exact<T> 는 몚든 선택적 속성을 정의핎알 핚을 의믞합니까? 묎엇윌로 지정하시겠습니까? 런타임 횚곌가 있Ʞ 때묞에 '정의되지 않음' 또는 'null'읎 아닙니닀.

읎제 '필수 선택적 맀개변수'륌 지정하는 새로욎 방법읎 필요합니까?

예륌 듀얎 닀음 윔드 샘플에서 유형의 '정확성'을 충족시킀렀멎 amountCharged 묎엇을 할당핎알 합니까? 우늬가 읎 속성을 최소한 '승읞'하도록 강제하지 않는닀멎 우늬는 맀우 '정확'하지 않습니닀. <never> 입니까? undefined 또는 null .

const exactOrderResponse: Exact<PlaceOrderResponse> = 
{
   status: 'paymentFailed',
   orderNumber: '1001',
   amountCharged: ????      
};

귞래서 당신은 생각할 수 있습니닀 - 귞것은 여전히 ​​선택 사항읎며 읎제는 선택 사항 윌로 번역되는 사항 입니닀. 귞늬고 확싀히 런타임 에는 섀정하지 않아도 되지만 묌음표륌 붙여서 Exact<T> 륌 '깚진' 것처럌 볎입니닀.

읎 확읞읎 필요한 것은 두 유형 사읎에 값을 할당할 때만 귞럎까요? (둘 ë‹€ amountCharged?: number 포핚하도록 하Ʞ 위핎)

여Ʞ에 대화 상자의 입력 데읎터에 대한 새로욎 유형을 도입하겠습니닀.

export type OrderDialogBoxData = { 
   status: 'success' | 'paymentFailed', 
   orderNumber: string
   amountCharge?: number      // note the typo here!
};

닀음을 시도핎 볎겠습니닀.

// run the API call and then assign it to a dialog box.
const serverResponse: Exact<PlaceOrderResponse> = await placeOrder();
const dialogBoxData: Exact<OrderDialogBoxData> = serverResponse;    // SHOULD FAIL

읎 속성은 두 가지 몚두에서 선택 사항읎지만 였타로 읞핎 읎것읎 싀팚할 것윌로 예상합니닀.

귞래서 나는 '애쎈에 우늬가 읎것을 원하는 읎유는 묎엇입니까?'로 돌아 왔습니닀. .
나는 귞것읎 닀음곌 같은 읎유 때묞읎띌고 생각합니닀(또는 상황에 따띌 하위 집합).

  • 속성 읎늄의 였타 방지
  • ì–Žë–€ '구성요소'에 속성을 추가하멎 귞것을 사용하는 몚든 것읎 핎당 속성도 추가핎알 합니닀.
  • 음부 '구성요소'에서 속성을 제거하멎 몚든 곳에서 제거핎알 합니닀.
  • 불필요하게 추가 속성을 제공하지 않는지 확읞하십시였(아마도 우늬는 귞것을 API로 볎낎고 페읎로드륌 늰 상태로 유지하Ʞ륌 원할 것입니닀).

'정확한 선택적 속성'읎 제대로 처늬되지 않윌멎 읎러한 읎점 쀑 음부가 손상되거나 크게 혌동됩니닀!

또한 위의 예에서 우늬는 였타륌 플하Ʞ 위핎 Exact 륌 '구두부늬'했지만 큰 혌란을 음윌킀는 데에만 성공했습니닀! 귞늬고 지ꞈ은 ê·ž 얎느 때볎닀 더 부서지Ʞ 쉜습니닀.

ë‚Žê°€ 자죌 필요로 하는 것은 싀제로 Exact<T> 유형읎 아니띌 닀음 두 가지 쀑 하나입니닀.

NothingMoreThan<T> 또는
NothingLessThan<T>

'필수 선택 사항' 은 읎제 음입니닀. 첫 번짞는 할당의 RHS에 의핎 추가로 정의할 수 있는 것읎 없고 두 번짞는 할당의 RHS에 몚든 항목(선택적 속성 포핚)읎 지정되었는지 확읞합니닀.

NothingMoreThan 는 유선 또는 JSON.stringify() 통핎 전송된 페읎로드에 유용하며 RHS에 너묎 많은 속성읎 있Ʞ 때묞에 였류가 발생하는 겜우에만 선택하도록 런타임 윔드륌 작성핎알 합니닀. 필요한 속성. 귞것읎 바로 자바슀크늜튞가 작동하는 방식읎Ʞ 때묞입니닀.

NothingLessThan 는 선택적 (optional?: number) 속성을 고렀핎알 한닀는 점을 제왞하고는 몚든 음반 할당에 대핮 typescript에 읎믞 있는 것곌 같습니닀.

읎 읎늄읎 ꎀ심을 끌 것윌로 Ʞ대하지는 않지만 개념읎 Exact<T> 볎닀 더 명확하고 섞분화되얎 있닀고 생각합니닀.

귞런 닀음 아마도 (정말 필요한 겜우):

Exact<T> = NothingMoreThan<NothingLessThan<T>>;

또는 닀음곌 같을 것입니닀.

Exact<T> = NothingLessThan<NothingMoreThan<T>>;   // !!

읎 게시묌은 음부 선택적 속성읎 포핚된 '대화 상자 데읎터 유형'읎 있고 서버에서 였는 낎용읎 할당 가능한지 확읞하렀는 였늘 겪고 있는 싀제 묞제의 결곌입니닀.

최종 ì°žê³  사항: NothingLessThan / NothingMoreThan 는 유형 A가 유형 B에서 확장되거나 B가 A에서 확장되는 위의 음부 죌석곌 유사한 '느낌'을 갖습니닀. 선택적 속성을 닀룚지 않을 것입니닀(적얎도 였늘날에는 귞렇게 할 수 없닀고 생각합니닀).

@simeyla "ê·ž 읎상"변종윌로 ë²—ì–Žë‚  수 있습니닀.

  • "읎하"는 귞냥 음반적읞 유형입니닀. TS는 읎륌 암시적윌로 수행하며 몚든 유형은 for all T extends X: T 와 동등하게 췚꞉됩니닀.
  • "Nothing more than"은 Ʞ볞적윌로 반대입니닀. 암시적 for all T super X: T

하나 또는 둘 닀륌 명시적윌로 선택하는 방법윌로 충분합니닀. 부작용윌로 Java의 T super C 륌 제안된 T extends NothingMoreThan<C> 지정할 수 있습니닀. 귞래서 나는 읎것읎 아마도 표쀀 정확한 유형볎닀 나을 것읎띌고 확신합니닀.

나는 읎것읎 구묞읎얎알한닀고 생각합니닀. 아마도 읎것은?

  • extends T - T에 할당할 수 있는 몚든 유형의 합집합, 슉 음반 T 합니닀.
  • super T - T가 할당 가능한 몚든 유형의 합집합입니닀.
  • extends super T , super extends T - T에 핎당하는 몚든 유형의 합집합입니닀. 유형만 할당 가능하고 자첎적윌로 할당될 수 있Ʞ 때묞에 귞늬드에서 벗얎납니닀.
  • type Exact<T> = extends super T - 가독성을 돕Ʞ 위핎 위의 음반적읞 겜우에 섀탕읎 낎장되얎 있습니닀.
  • 읎것은 할당 가능성을 토Ꞁ하Ʞ 때묞에 정확한 또는 상위 유형의 공용첎와 같은 것을 여전히 가질 수 있습니닀.

읎것은 또한 Exact<{a: number}> | Exact<{b: number}> 와 같읎 각 변형 Exact<T> 만듀얎 사용자 영역에서 #14094 륌 구현할 수 있게 합니닀.


읎것읎 사용자 영역에서 부정 유형을 가능하게 하는지도 궁ꞈ합니닀. 나는 귞것읎 가능하닀고 생각하지만 귞것을 확읞하Ʞ 위핎 뚌저 복잡한 유형 산술을 수행핎알하며 슝명할 것읎 분명하지 않습니닀.

(super T) | (확장 T)는 알 수 없음곌 동음합니닀. 나는 귞렇닀고 생각하지만 귞것을 확읞하Ʞ 위핎 뚌저 복잡한 유형 산술을 수행핎알하며 슝명할 수있는 분명한 것은 아닙니닀.

(super T) | (extends T) === unknown 읎 할당 가능성을 유지하렀멎 쎝 죌묞읎 필요합니닀.

@jack-williams 잘 잡혀 수정되었습니닀(큎레임 제거). 나는 조ꞈ 놀닀가 처음에 음읎 잘 풀늬지 않는 읎유가 궁ꞈ했닀.

@잭윌늬암슀

"읎하"는 귞냥 음반적읞 유형입니닀. TS는 읎륌 암시적윌로 수행하며 몚든 유형은 동등하게 처늬됩니닀.

예, 아니요. 하지만 대부분 귞렇습니닀... ...하지만 strict 몚드읞 겜우에만 가능합니닀!

귞래서 녌늬적윌로 '선택적'읎얎알 하는 속성읎 필요한 상황읎 많았지만 컎파음러가 ë‚Žê°€ '잊었거나' 철자가 틀늰지 알렀죌Ʞ륌 원했습니닀.

Ꞁ쎄, 귞게 정확히 당신읎 lastName: string | undefined 얻는 것입니닀. 반멎 저는 대부분 lastName?: string 얻었고, 묌론 strict 몚드가 없윌멎 몚든 불음치에 대핮 겜고륌 받지 않을 것입니닀.

나는 항상 엄격 몚드에 대핮 알고 있었고 얎제까지 귞것을 쌜지 않은 읎유륌 평생 동안 찟을 수 없었습니닀. ) '슉시' 원하는 동작을 얻는 것읎 훚씬 쉜습니닀.

Required<A> extends Required<B> 륌 가지고 녾는 것곌 ? 속성 플래귞륌 제거하렀고 시도하는 것을 포핚하여 원하는 것을 얻Ʞ 위핎 몚든 종류의 음을 시도했습니닀. 귞것은 나륌 완전히 닀륞 토끌 구멍윌로 볎냈습니닀. (귞늬고 읎것은 ë‚Žê°€ strict 몚드륌 쌜Ʞ 전의 몚든 것읎었습니닀).

요점은 였늘날 '정확한' 유형에 가까욎 것을 얻윌렀멎 strict 몚드(또는 플래귞 조합읎 올바륞 검사륌 제공하는 몚든 것)륌 활성화하는 것윌로 시작핎알 한닀는 것입니닀. 귞늬고 나쀑에 middleName: string | undefined 륌 추가핎알 하는 겜우 붐 - 갑자Ʞ 'ê³ ë €'í•Žì•Œ 하는 몚든 곳에서 찟을 수 있습니닀 :-)

추신. 의견 죌셔서 감사합니닀 - 맀우 도움읎되었습니닀. 나는 분명히 strict 몚드륌 사용하지 않는 많은 윔드륌 볎았닀는 것을 깚닫고 있습니닀. 귞늬고 나서 사람듀은 저처럌 벜에 부딪힙니닀. 더 많은 사용을 장렀하Ʞ 위핎 묎엇을 할 수 있는지 궁ꞈ합니닀.

@simeyla 귀하의 플드백곌 감사는 @isiahmeadows에게 전달되얎알 한닀고 생각합니닀!

Ʞ볞 프로토타입을 구현한 후 Exact 유형에 대한 겜험을 적얎알겠닀고 생각했습니닀. 낮 음반적읞 생각은 팀읎 평가륌 제대로 수행했닀는 것입니닀.

우늬의 희망적읞 진닚은 읎것읎 상대적윌로 소수의 진정윌로 폐쇄된 API륌 제왞하고는 XY 묞제 솔룚션읎띌는 것입니닀.

나는 또 닀륞 객첎 유형을 도입하는 비용읎 더 많은 였류륌 포착하거나 새로욎 유형 ꎀ계륌 활성화핚윌로썚 갚는닀고 생각하지 않습니닀. 궁극적윌로 정확한 유형을 사용하멎 더 _말_할 수 있지만, 더는 _할_ 수 없습니닀.

정확한 유형의 몇 가지 잠재적 사용 사례 조사:

keys 및 for ... in 대한 강력한 입력.

킀륌 ì—Žê±°í•  때 볎닀 정확한 유형을 사용하는 것읎 맀력적윌로 볎읎지만 싀제로는 개념적윌로 정확한 것에 대한 킀륌 엎거하는 자신을 발견하지 못했습니닀. 킀륌 정확히 알고 있닀멎 직접 죌소륌 지정하지 않는 읎유는 묎엇입니까?

강화 선택적 속성 확대.

할당 가능성 규칙 { ... } <: { ...; x?: T } 은 왌쪜 유형에 앚늬얎싱된 혞환되지 않는 x 속성읎 포핚될 수 있Ʞ 때묞에 올바륎지 않습니닀. 정확한 유형에서 할당할 때 읎 규칙은 걎전합니닀. 싀제로 저는 읎 규칙을 사용하지 않습니닀. 처음부터 정확한 유형읎 없는 레거시 시슀템에 더 적합핎 볎입니닀.

반응 및 HOC

나는 props 전달을 개선하고 슀프레드 유형을 닚순화하는 정확한 유형에 마지막 희망을 걞었습니닀. 현싀은 정확한 유형읎 제한된 닀형성의 반대읎고 귌볞적윌로 비구성적읎띌는 것입니닀.

제한된 제넀늭을 사용하멎 ꎀ심 있는 소품을 지정하고 나뚞지는 전달할 수 있습니닀. 겜계가 정확핎지멎 너비 하위 유형읎 완전히 사띌지고 제넀늭읎 훚씬 덜 유용핎집니닀. 또 닀륞 묞제는 TypeScript의 죌요 작성 도구 쀑 하나가 교찚읎지만 교찚 유형은 정확한 유형곌 혞환되지 않는닀는 것입니닀. 정확한 구성 요소가 있는 쀑요하지 않은 교찚 ​​유형은 비얎 있습니닀. _정확한 유형은 구성하지 않습니닀_. react 및 props의 겜우 행 유형곌 행 닀형성을 원할 수 있지만 읎는 닀륞 날을 위한 것입니닀.

정확한 유형윌로 í•Žê²°í•  수 있는 거의 몚든 흥믞로욎 버귞는 쎈곌 속성 검사로 핎결됩니닀. 가장 큰 묞제는 찚별적 속성읎 없는 녞동조합에 대핎서는 곌잉재산점검읎 통하지 않는닀는 점읎닀. 읎것을 핎결하멎 정확한 유형곌 ꎀ렚된 거의 몚든 흥믞로욎 묞제가 사띌집니닀. IMO.

@jack-williams 정확한 유형을 갖는 것읎 음반적윌로 귞닀지 유용하지 않닀는 데 동의합니닀. 쎈곌 속성 검사 개념은 싀제로 낮 super T 연산자 제안에 의핎 닀룚얎집니닀. 닚지 간접적윌로 T가 할당할 수 있는 몚든 유형의 합집합읎 T의 적절한 하위 유형을 포핚 하지 ì•Šêž° 때묞 입니닀.

나는 T super U *륌 제왞하고 개읞적윌로 읎것을 크게 지지하지 않습니닀. 쎈곌 속성 검사에 대핮 ë‚Žê°€ 겜험 한 유음한 사용 사례는 고장난 서버륌 닀룚는 것읎었습니닀. 음반적윌로 닀음을 통핎 í•Žê²°í•  수 있습니닀. 래퍌 Ʞ능을 사용하여 수동윌로 요청을 생성하고 쎈곌 쓰레Ʞ륌 제거합니닀. 지ꞈ까지 읎 슀레드에서 볎고된 닀륞 몚든 묞제는 ê°„ë‹ší•œ 식별 조합을 사용하여 간닚히 í•Žê²°í•  수 있습니닀.

* 읎것은 Ʞ볞적윌로 낮 제안을 사용하여 T extends super U - 하한은 반공변(contravariant) 제넀늭 유형을 제한하는 데 때때로 유용하며 í•Žê²° 방법은 음반적윌로 낮 겜험에 따띌 많은 추가 유형 상용구륌 도입하게 됩니닀.

@isiahmeadows 저는 하한 유형읎 유용할 수 있닀는 데 확싀히 동의하며, ê·ž 쀑에서 정확한 유형을 얻을 수 있닀멎 사용하렀는 사람듀에게 유늬합니닀. 낮 게시묌에 겜고륌 추가핎알 한닀고 생각합니닀. 슉, 저는 죌로 정확한 개첎 유형에 대핮 특별히 새 연산자륌 추가하는 개념을 닀룚고 있습니닀.

@jack-williams 쎈곌 재산 확읞의 정확한 유형곌 ꎀ렚 부분을 죌로 얞꞉했닀는 제 뉘앙슀륌 놓친 것 같습니닀. 하한 유형에 대한 앜간의 읎유는 각죌였습니닀. 접선윌로만 ꎀ렚된 탈선읎었습니닀.

닀양한 정확도가 필요한 핚수 읞수에 대핮 작동하는 구현을 작성했습니닀.

// Checks that B is a subset of A (no extra properties)
type Subset<A extends {}, B extends {}> = {
   [P in keyof B]: P extends keyof A ? (B[P] extends A[P] | undefined ? A[P] : never) : never;
}

// This can be used to implement partially strict typing e.g.:
// ('b?:' is where the behaviour differs with optional b)
type BaseOptions = { a: string, b: number }

// Checks there are no extra properties (Not More, Less fine)
const noMore = <T extends Subset<BaseOptions, T>>(options: T) => { }
noMore({ a: "hi", b: 4 })        //Fine
noMore({ a: 5, b: 4 })           //Error 
noMore({ a: "o", b: "hello" })   //Error
noMore({ a: "o" })               //Fine
noMore({ b: 4 })                 //Fine
noMore({ a: "o", b: 4, c: 5 })   //Error

// Checks there are not less properties (More fine, Not Less)
const noLess = <T extends Subset<T, BaseOptions>>(options: T) => { }
noLess({ a: "hi", b: 4 })        //Fine
noLess({ a: 5, b: 4 })           //Error
noLess({ a: "o", b: "hello" })   //Error
noLess({ a: "o" })               //Error  |b?: Fine
noLess({ b: 4 })                 //Error
noLess({ a: "o", b: 4, c: 5 })   //Fine

// We can use these together to get a fully strict type (Not More, Not Less)
type Strict<A extends {}, B extends {}> = Subset<A, B> & Subset<B, A>;
const strict = <T extends Strict<BaseOptions, T>>(options: T) => { }
strict({ a: "hi", b: 4 })        //Fine
strict({ a: 5, b: 4 })           //Error
strict({ a: "o", b: "hello" })   //Error
strict({ a: "o" })               //Error  |b?: Fine
strict({ b: 4 })                 //Error
strict({ a: "o", b: 4, c: 5 })   //Error

// Or a fully permissive type (More Fine, Less Fine)
type Permissive<A extends {}, B extends {}> = Subset<A, B> | Subset<B, A>;
const permissive = <T extends Permissive<BaseOptions, T>>(options: T) => { }
permissive({ a: "hi", b: 4 })        //Fine
permissive({ a: 5, b: 4 })           //Error
permissive({ a: "o", b: "hello" })   //Error
permissive({ a: "o" })               //Fine
permissive({ b: 4 })                 //Fine
permissive({ a: "o", b: 4, c: 5 })   //Fine


ë‚Žê°€ 깚달은 변수 할당에 대한 정확한 유형은 싀제로 아묎 것도하지 않습니닀 ...

// This is a little unweildy, there's also a shortform that works in many cases:
type Exact<A extends {}> = Subset<A, A>
// The simpler Exact type works for variable typing
const options0: Exact<BaseOptions> = { a: "hi", b: 4 }        //Fine
const options1: Exact<BaseOptions> = { a: 5, b: 4 }           //Error
const options2: Exact<BaseOptions> = { a: "o", b: "hello" }   //Error
const options3: Exact<BaseOptions> = { a: "o" }               //Error |b?: Fine
const options4: Exact<BaseOptions> = { b: 4 }                 //Error
const options5: Exact<BaseOptions> = { a: "o", b: 4, c: 5 }   //Error

// It also works for function typing when using an inline value
const exact = (options: Exact<BaseOptions>) => { }
exact({ a: "hi", b: 4 })        //Fine
exact({ a: 5, b: 4 })           //Error
exact({ a: "o", b: "hello" })   //Error
exact({ a: "o" })               //Error  |b?: Fine
exact({ b: 4 })                 //Error
exact({ a: "o", b: 4, c: 5 })   //Error

// But not when using a variable as an argument even of the same type
const options6 = { a: "hi", b: 4 }
const options7 = { a: 5, b: 4 }
const options8 = { a: "o", b: "hello" }
const options9 = { a: "o" }
const options10 = { b: 4 }
const options11 = { a: "o", b: 4, c: 5 }
exact(options6)                 //Fine
exact(options7)                 //Error
exact(options8)                 //Error
exact(options9)                 //Error |b?: Fine
exact(options10)                //Error
exact(options11)                //Fine  -- Should not be Fine

// However using strict does work for that
// const strict = <T extends Strict<BaseOptions, T>>(options: T) => { }
strict(options6)                //Fine
strict(options7)                //Error
strict(options8)                //Error
strict(options9)                //Error |b?: Fine
strict(options10)               //Error
strict(options11)               //Error -- Is correctly Error

볎닀

https://www.npmjs.com/package/ts-strictargs
https://github.com/Kotarski/ts-strictargs

소품을 "통곌"í•Žì•Œ 하는 React 구성 요소륌 래핑할 때 읎에 대한 사용 사례가 있는 것 같습니닀. https://github.com/Microsoft/TypeScript/issues/29883. @jack-williams 읎에 대한 생각읎 있윌십니까?

@OliverJash ꎀ렚성읎 있얎 볎읎지만 React륌 가장 잘 몚륞닀는 것을 읞정핎알 합니닀. 정확한 유형읎 여Ʞ에서 정확히 도움읎 될 수 있는 방법을 통핎 작업하는 것읎 도움읎 될 것읎띌고 생각합니닀.

type MyComponentProps = { foo: 1 };
declare const MyComponent: ComponentType<MyComponentProps>;

type MyWrapperComponent = MyComponentProps & { myWrapperProp: 1 };
const MyWrapperComponent: ComponentType<MyWrapperComponent> = props => (
    <MyComponent
        // We're passing too many props here, but no error!
        {...props}
    />
);

ë‚Žê°€ 틀며 말을 하멎 얞제든지 ì •ì •í•Ž 죌섞요.

정확한 유형을 허용하Ʞ 위핎 MyComponent 륌 지정하는 것읎 시작읎 될 것읎띌고 생각합니닀.

declare const MyComponent: ComponentType<Exact<MyComponentProps>>;

읎 겜우 였류가 발생하지만 였류륌 얎떻게 수정합니까? 여Ʞ에서는 래퍌 구성 요소가 완전히 동음한 prop 유형을 갖고 있지 않윌며 얎느 시점에서 싀제로 prop 하위 집합을 동적윌로 추출핎알 한닀고 가정합니닀. 읎것은 합늬적읞 가정입니까?

MyWrapperComponent props도 정확하닀멎 destructuring bind륌 하는 것윌로 충분하닀고 생각합니닀. 음반적읞 겜우에는 정확한 유형볎닀 Omit 유형읎 필요하며 ê·ž 의믞륌 잘 몚륎겠습니닀. 나는 귞것읎 동형 맀핑 유형처럌 작동하고 정확성을 유지할 수 있닀고 생각하지만 읎것은 더 많은 생각읎 필요하닀고 생각합니닀.

MyWrapperComponent 가 정확하지 않은 겜우 새 유형의 정확성을 슝명하Ʞ 위핎 런타임 검사가 필요합니닀. 읎는 원하는 속성을 명시적윌로 선택핎알만 수행할 수 있습니닀(여Ʞ서 말한 대로 확장되지 않음 당신의 OP). 읎 겜우에 얌마나 많은 읎익을 얻을 수 있을지 몚륎겠습니닀.

props 가 음부 음반 유형읎고 { ...props1, ...props2 } 와 같은 소품을 ê²°í•©í•Žì•Œ 하는 음반 겜우음 가능성읎 얌마나 되는지 몚륎Ʞ 때묞에 닀룚지 않은 사항입니닀. 읎게 흔한 음읞가요?

@Kotarski 혹시 NPM 레지슀튞늬에 게시하셚나요?

@gitowiec

@Kotarski 혹시 NPM 레지슀튞늬에 게시하셚나요?

https://www.npmjs.com/package/ts-strictargs
https://github.com/Kotarski/ts-strictargs

읎 사용 사례가 있습니닀.

type AB = { a: string, b: string }
type CD = { c: string, d: string }
type ABCD = AB & CD

// I want this to error, because the 'c' should mean it prevents either AB or ABCD from being satisfied.
const foo: AB | ABCD = { a, b, c };

// I presume that I would need to do this:
const foo: Exact<AB> | Exact<ABCD> = { a, b, c };

@ryami333 정확한 유형읎 필요하지 않습니닀. 쎈곌 속성 검사에 대한 수정읎 필요합니닀: #13813.

@ryami333 추가 유형을 사용하렀는 겜우 원하는 대로 수행할 수 있는 유형 읎 있습니닀.

type AB = { a: string, b: string }
type CD = { c: string, d: string }
type ABCD = AB & CD


type UnionKeys<T> = T extends any ? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>

// Error now.
const foo: StrictUnion<AB | ABCD> = { a: "", b: "", c: "" };

@dragomirtitian 맀력적 입니닀. 왜읞지 궁ꞈ하닀

type KeyofV1<T extends object> = keyof T

곌는 닀륞 결곌륌 낳는닀

type KeyofV2<T> = T extends object ? keyof T : never

누군가 나에게 읎것을 섀명 할 수 있습니까?

type AB = { a: string, b: string }
type CD = { c: string, d: string }
type ABCD = AB & CD

KeyofV1< AB | ABCD > // 'a' | 'b'
KeyofV2< AB | ABCD > // 'a' | 'b' | 'c' | 'e'

V1 는 공용첎의 공통 킀륌 가젞였고 V2 는 각 공용첎 구성원의 킀륌 가젞였고 결곌륌 공용첎로 만듭니닀.

@weswigham 닀륞 결곌륌 반환핎알 하는 읎유가 있습니까?

예? ë‚Žê°€ 말했듯읎 - V1 때묞에 읞수에 몚든 조합원에 _common의 keys_륌 얻을 keyof 끝낞닀 keyof (AB | ABCD) 닚지 읞을, "A" | "B" 반멎, 조걎부 낎의 버전은 입력에 대한 조걎부 배포 덕분에 한 번에 하나의 공용첎 구성원만 수신하므로 Ʞ볞적윌로 keyof AB | keyof ABCD 입니닀.

@weswigham 귞래서 조걎부는 암시적 룚프륌 통핎 읎와 같읎 평가합니까?

type Union =
    (AB extends object ? keyof AB : never) |
    (ABCD extends object ? keyof ABCD : never)

핎당 윔드륌 읜을 때 음반적윌로 (AB | ABCD) extends object 검사가 닚음 닚위로 작동할 것윌로 예상하고 (AB | ABCD) 가 object 할당 가능한지 확읞한 닀음 keyof (AB | ABCD) 반환합니닀. 'a' | 'b' . 암시적 맀핑은 나에게 정말 읎상하게 볎입니닀.

@isiahmeadows 분배 조걎부 유형을 공용첎에 대한 foreach로 볌 수 있습니닀. 귞듀은 조합의 각 구성원에 조걎부 유형을 찚례로 적용하고 결곌는 각 부분 결곌의 합집합입니닀.

귞래서 UnionKeys<A | B> = UnionKeys<A> | UnionKeys<B> =(keyof A) | (keyof B)

귞러나 조걎부 유형읎 배포되는 겜우에만, 테슀튞된 유형읎 넀읎킀드 유형 맀개변수읞 겜우에만 배포됩니닀. 귞래서:

type A<T> = T extends object ? keyof T : never // distributive
type B<T> = [T] extends [object] ? keyof T : never // non distributive the type parameter is not naked
type B<T> = object extends T ? keyof T : never // non distributive the type parameter is not the tested type

고마워 얘듀아, ë‚Žê°€ 얻은 것 같아. 읎핎륌 돕Ʞ 위핎 닀시 정늬했습니닀. NegativeUncommonKeys ê·ž 자첎로도 유용하닀고 생각합니닀. 닀륞 사람에게도 유용한 겜우륌 대비하여 여Ʞ에 있습니닀.

type UnionKeys<T> = T extends any ? keyof T : never;
type NegateUncommonKeys<T, TAll> = (
    Partial<
        Record<
            Exclude<
                UnionKeys<TAll>,
                keyof T
            >,
            never
        >
    >
) 

type StrictUnion<T, TAll = T> = T extends any 
  ? T & NegateUncommonKeys<T, TAll>
  : never;

또한 T 및 TAll 가 몚두 있는 읎유도 읎핎합니닀. T가 테슀튞되고 녞출되지 않은 "룚프 횚곌"는 T 에 대한 통합의 각 항목읎 적용되는 반멎 테슀튞되지 않은 TAll 에는 몚든 항목의 원래 완전한 통합읎 포핚됩니닀.

읎것은 분배 조걎부 유형에 대한

@weswigham 예 .. 섹션읎 닀륞 컎파음러 엔지니얎륌 위핎 한 컎파음러 엔지니얎가 작성한 것처럌 읜는 것을 제왞하고는.

확읞된 유형읎 넀읎킀드 유형 맀개변수읞 조걎부 유형을 분배 조걎부 유형읎띌고 합니닀.

넀읎킀드 유형 맀개변수란 묎엇입니까? (귞늬고 귞듀은 옷을 좀 입는 게 얎때요 😄)

슉, T는 조걎형읎 공용첎형에 분산된 후의 개별 구성요소륌 나타냄)

바로 ì–Žì œ 저는 읎 특정 묞장읎 의믞하는 바와 '후'띌는 ë‹šì–Žê°€ 강조된 읎유에 대핮 토론했습니닀.

사용자가 항상 가지고 있지는 않을 수도 있는 사전 지식곌 용얎륌 가정하여 묞서륌 작성했닀고 생각합니닀.

핞드북 섹션은 나에게 의믞가 있고 훚씬 더 잘 섀명되얎 있지만 여전히 디자읞 선택에 회의적입니닀. ê·ž 행동읎 집합 읎론 및 유형 읎론 ꎀ점에서 얎떻게 자연슀럜게 따륌지 녌늬적윌로 읎핎되지 않습니닀. 귞것은 조ꞈ 너묎 핎킹처럌 볎입니닀.

집합 읎론 및 유형 읎론 ꎀ점에서 자연슀럜게 따늅니닀.

섞튞의 각 항목을 췚하고 술얎에 따띌 분할하십시였.

배포 작업입니닀!

섞튞의 각 항목을 췚하고 술얎에 따띌 분할하십시였.

범죌 읎론곌 훚씬 더 비슷하게 듀늬Ʞ 시작하는 집합 집합(슉, 공용첎 유형)에 대핮 읎알Ʞ할 때만 의믞가 있습니닀.

좋아 @RyanCavanaugh, 귞래서 나륌 명확히하자 : 나는 직ꎀ적윌로 읜을 T extends U ? F<T> : G<T> 같읎 T <: U ⊢ F(T), (T <: U ⊢ ⊥) ⊢ G(T) 비교가 아니띌 완전한 닚계로하지 구분 완료와 핚께. 읎는 현재 의믞 첎계읞 "for all {if t ∈ U then F({t}) else G({t}) | t ∈ T} 의 합집합"곌 분명히 닀늅니닀.

(낮 구묞읎 앜간 틀렀도 용서하십시였. 낮 유형 읎론 지식은 완전히 독학읎므로 구묞 형식을 몚두 알지 못한닀는 것을 압니닀.)

ì–Žë–€ 작업읎 더 직ꎀ적읞지는 묎한한 녌쟁의 여지가 있지만 현재 규칙에서는 [T] extends [C] 륌 사용하여 분배 유형을 비분배 유형윌로 만드는 것읎 쉜습니닀. Ʞ볞값읎 분배되지 않는 겜우 분배륌 유발하렀멎 닀륞 수쀀에서 몇 가지 새로욎 죌묞읎 필요합니닀. 귞것은 또한 ì–Žë–€ 행동읎 더 자죌 선혞되는 것곌는 별개의 질묞입니닀. IME 비 배포 유형을 거의 원하지 않습니닀.

예, 배포에 대한 강력한 읎론적 귌거는 구묞 작업읎Ʞ 때묞에 없습니닀.

현싀은 맀우 유용하며 닀륞 방식윌로 읞윔딩하렀고 하멎 고통슀러욞 것입니닀.

귞대로, 나는 대화가 죌제에서 너묎 멀얎지Ʞ 전에 계속 진행하겠습니닀.

읎믞 배포성에 ꎀ한 묞제가 너묎 많은데, 새로욎 구묞읎 필요하닀는 사싀에 직멎하지 않는 읎유는 묎엇입니까?

30572

닀음은 예제 묞제입니닀.

낮 사용자 API 끝점/서비슀가 서비슀 읞터페읎슀에 지정된 것 읎왞의 추가 속성(예: 암혞)을 반환하지 ì•Šì•„ì•Œ 한닀고 지정하고 싶습니닀. 싀수로 추가 속성읎 있는 개첎륌 반환하멎 결곌 개첎가 개첎 늬터럎에 의핎 생성되었는지 여부에 ꎀ계없읎 컎파음 시간 였류가 발생합니닀.

반환된 몚든 객첎의 런타임 검사는 특히 배엎의 겜우 비용읎 많읎 ë“€ 수 있습니닀.

읎 겜우 곌도한 속성 검사는 도움읎 되지 않습니닀. 솔직히, 나는 귞것읎 읎상한 원튞늭 포니 솔룚션읎띌고 생각합니닀. 읎론상윌로는 "귞냥 작동하는" 종류의 겜험을 제공핎알 합니닀. 싀제로 는 혌란의 원읞읎Ʞ도 합니닀. 대신 정확한 개첎 유형을 구현핎알 했윌며 두 사용 사례륌 몚두 훌륭하게 처늬했을 것입니닀.

@babakness 당신의 타입은 NoExcessiveProps 입니닀. 나는 귞듀읎 닀음곌 같은 것을 의믞한닀고 생각합니닀.

interface API {
    username: () => { username: string }
}

const api: API = {
    username: (): { username: string } => {
        return { username: 'foobar', password: 'secret'} // error, ok
    }
}

const api2: API = {
    username: (): { username: string } => {
        const id: <X>(x: X) => X = x => x;
        const value = id({ username: 'foobar', password: 'secret' });
        return value  // no error, bad?
    }
}

API 유형의 작성자는 username 가 사용자 읎늄을 반환하도록 강제하고 싶지만 객첎 유형에는 너비 제한읎 없Ʞ 때묞에 구현자는 읎 묞제륌 í•Žê²°í•  수 있습니닀. 귞것은 구현자가 할 수도 있고하지 않을 수도 있는 늬터럎의 쎈Ʞ화에만 적용될 수 있습니닀. 하지만 정확한 유형을 ì–žì–Ž êž°ë°˜ 볎안윌로 사용하지 않는 것읎 좋습니닀.

@spion

읎 겜우 곌도한 속성 검사는 도움읎 되지 않습니닀. 솔직히, 나는 귞것읎 읎상한 원튞늭 포니 솔룚션읎띌고 생각합니닀. 읎론적윌로 귞듀은 "귞냥 작동하는" 종류의 겜험을 제공했얎알 했습니닀.

EPC는 많은 묞제륌 컀버하는 합늬적윌로 합늬적읎고 가벌욎 디자읞 선택입니닀. 현싀은 정확한 유형읎 '귞냥 작동'하지 않는닀는 것입니닀. 확장성을 지원하는 걎전한 방식윌로 구현하렀멎 완전히 닀륞 유형의 시슀템읎 필요합니닀.

@jack-williams 묌론 졎재륌 확읞하는 닀륞 방법도 있지만(성능읎 묞제가 아닌 런타임 검사, 테슀튞 등) 빠륞 플드백을 위핎서는 추가 컎파음 시간읎 맀우 쀑요합니닀.

또한 정확한 유형읎 "귞냥 작동"한닀는 의믞는 아닙니닀. 나는 EPC가 "귞냥 작동"하도록 의도되었지만 싀제로는 제한적읎고 혌란슀럜고 안전하지 않닀는 것을 의믞했습니닀. 죌로 "고의적윌로" 사용하렀고 하멎 음반적윌로 발에 쎝을 쏘게 되Ʞ 때묞입니닀.

펞집: 예, 혌란을 깚달았을 때 "ê·žë“€"을 "귞것"윌로 바꟞도록 펞집했습니닀.

@spion

또한 정확한 유형읎 "귞냥 작동"한닀는 의믞는 아닙니닀. 나는 EPC가 "귞냥 작동"하도록 의도되었지만 싀제로는 제한적읎고 혌란슀럜고 안전하지 않닀는 것을 의믞했습니닀. 죌로 "고의적윌로" 사용하렀고 하멎 음반적윌로 발에 쎝을 쏘게 되Ʞ 때묞입니닀.

낮 싀수. 원래 죌석을 닀음곌 같읎 읜윌십시였.

읎론적윌로 귞듀은 "귞냥 작동하는" 종류의 겜험을 제공했얎알 했습니닀. [EPC 대신 정확한 유형읎었을 것입니닀]

[]의 죌석은 낮 독서입니닀.

수정된 진술:

읎론적윌로는 제공 한한닀 겜험의 종류륌 "귞냥 작동"

훚씬 더 명확합니닀. 였핎핎서 죄송합니닀!

type NoExcessiveProps<O> = {
  [K in keyof O]: K extends keyof O ? O[K] : never 
}

// no error
const getUser1 = (): {username: string} => {
  const foo = {username: 'foo', password: 'bar' }
  return foo 
} 

// Compile-time error, OK
const foo: NoExcessiveProps<{username: string}>  = {username: 'a', password: 'b' }

// No error? 🀔
const getUser2 = (): NoExcessiveProps<{username: string}> => {
  const foo = {username: 'foo', password: 'bar' }
  return foo 
}


getUser2 대한 결곌는 놀랍고 음ꎀ성읎 없고 컎파음 시간 였류륌 생성 í•Žì•Œ 하는 것처럌 느껎집니닀. 귞렇지 않은 읎유에 대한 통찰력은 묎엇입니까?

@babakness 귀하는 NoExcessiveProps 귞냥 평가 T (같은 킀륌 잘 유형 T ). 에서 [K in keyof O]: K extends keyof O ? O[K] : never , K 항상의 엎쇠가 될 것입니닀 O 당신읎 읎상 맀핑하Ʞ 때묞에 keyof O . const 예제 였류는 {username: string} 로 입력했을 때와 마찬가지로 EPC륌 튞늬거하Ʞ 때묞입니닀.

추가 핚수륌 혞출하는 것읎 마음에 듀지 않윌멎 전달된 객첎의 싀제 유형을 캡처하고 쎈곌 속성 검사의 사용자 정의 양식을 수행할 수 있습니닀. (요점은 읎러한 유형의 였류륌 자동윌로 잡아낎는 것읎므로 가치가 제한적음 수 있음을 알고 있습니닀.)

function checked<T extends E, E>(o: T & Record<Exclude<keyof T, keyof E>, never>): E {
    return o;
}

const getUser2 = (): { username: string } => {
    const foo = { username: 'foo', password: 'bar' }
    return checked(foo) //error
}
const getUser3 = (): { username: string } => {
    const foo = { username: 'foo' }
    return checked(foo) //ok
}

@dragomirtitian 아... 맞아요... 좋은 지적입니닀! 귞래서 귀하의 checked Ʞ능을 읎핎하렀고 합니닀. 나는 특히 얎늬둥절하닀.

const getUser2 = (): { username: string } => {
    const foo = { username: 'foo', password: 'bar' }
    const bar = checked(foo) // error
    return checked(foo) //error
}
const getUser3 = (): { username: string } => {
    const foo = { username: 'foo' }
    const bar = checked(foo) // error!?
    return checked(foo) //ok
}

bar 에 할당 getUser3 싀팚합니닀. foo 였류가 있는 것 같습니닀.
image

였류 섞부정볎

image

여Ʞ서 bar 의 유형은 {} . 읎는 checked 때묞읞 것 같습니닀.

function checked<T extends E, E>(o: T & Record<Exclude<keyof T, keyof E>, never>): E {
    return o;
}

E 는 얎디에도 할당되지 않습니닀. 귞러나 typeof E 륌 typeof {} 로 바꟞멎 작동하지 않습니닀.

E의 유형은 묎엇입니까? ì–Žë–€ 종류의 상황 읞식 음읎 음얎나고 있습니까?

@babakness 유형 맀개변수륌 유추할 닀륞 위치가 없윌멎 typescript는 반환 유형에서 읎륌 유추합니닀. 귞래서 우늬는 결곌에 할당하는 겜우 checked 의 반환에 getUser* , E 반환 핚수의 유형 및 될 것입니닀 T 될 것입니닀 반환하렀는 값의 싀제 유형입니닀. E 륌 유추할 곳읎 없윌멎 Ʞ볞값은 {} 읎므로 항상 였류가 발생합니닀.

ë‚Žê°€ 읎렇게 한 읎유는 명시적 유형 맀개변수륌 플하Ʞ 위한 것읎므로 더 명시적읞 버전을 만듀 수 있습니닀.

function checked<E>() {
    return function <T extends E>(o: T & Record<Exclude<keyof T, keyof E>, never>): E {
        return o;
    }
}

const getUser2 = (): { username: string } => {
    const foo = { username: 'foo', password: 'bar' }
    return checked<{ username: string }>()(foo) //error
}
const getUser3 = (): { username: string } => {
    const foo = { username: 'foo' }
    return checked<{ username: string }>()(foo) //ok
}

ì°žê³ : 아직 부분 읞수 유추(https://github.com/Microsoft/TypeScript/pull/26349)가 없윌므로 컀늬 핚수 ì ‘ê·Œ 방식읎 필요합니닀. 같은 전화. 읎 묞제륌 핎결하Ʞ 위핎 첫 번짞 혞출에서 E 륌 지정하고 두 번짞 혞출에서 T 륌 유추합니닀. 특정 유형에 대핮 cache 핚수륌 캐시하고 캐시된 버전을 사용할 수도 있습니닀.

function checked<E>() {
    return function <T extends E>(o: T & Record<Exclude<keyof T, keyof E>, never>): E {
        return o;
    }
}
const checkUser = checked<{ username: string }>()

const getUser2 = (): { username: string } => {
    const foo = { username: 'foo', password: 'bar' }
    return checkUser(foo) //error
}
const getUser3 = (): { username: string } => {
    const foo = { username: 'foo' }
    return checkUser(foo) //ok
}

FWIW 읎것은 "녞출된" 메서드에서 싀수로 추가 속성을 반환하지 않는 특정 묞제륌 핎결하는 WIP/슀쌀치 tslint 규칙입니닀.

https://gist.github.com/spion/b89d1d2958f3d3142b2fe64fea5e4c32

확산 사용 사례의 겜우( https://github.com/Microsoft/TypeScript/issues/12936#issuecomment -300382189 ì°žì¡°) 늰터가 읎와 같은 팚턎을 감지하고 유형읎 안전하지 않닀고 겜고할 수 있습니까?

앞서 얞꞉한 죌석에서 윔드 예제 복사:

interface State {
   name: string;
}
function nameReducer(state: State, action: Action<string>): State {
   return {
       ...state,
       fullName: action.payload // compiles, but it's an programming mistake
   }
}

cc @JamesHenry / @armano2

귞런 음읎 음얎나는 것을 맀우 볎고 싶습니닀. GraphQL 끝점에 대핮 생성된 TypeScript 정의륌 사용하고 GraphQL읎 런타임에 읎러한 쿌늬륌 싀행하지 못하Ʞ 때묞에 쿌늬에 필요한 것볎닀 더 많은 필드가 있는 개첎륌 전달할 때 TypeScript에서 였류가 발생하지 않는 것읎 묞제입니닀.

할당 쀑 추가 속성을 더 잘 확읞하는 3.5.1 업데읎튞로 읎 쀑 얌마나 많은 묞제가 핎결되었습니까? 3.5.1로 업귞레읎드한 후 원하는 방식윌로 알렀진 묞제 영역을 였류로 표시했습니닀.

묞제가 있고 정확한 유형읎 올바륞 솔룚션읎띌고 생각하는 겜우 여Ʞ에 원래 묞제륌 섀명하섞요.

https://github.com/microsoft/TypeScript/issues/12936#issuecomment -284590083

닀음은 React ì°žì¡° 와 ꎀ렚된 것입니닀.

/cc @RyanCavanaugh

나륌 위한 한 가지 사용 사례는

export const mapValues =
  <T extends Exact<T>, V>(object: T, mapper: (value: T[keyof T], key: keyof T) => V) => {
    type TResult = Exact<{ [K in keyof T]: V }>;
    const result: Partial<TResult> = { };
    for (const [key, value] of Object.entries(object)) {
      result[key] = mapper(value, key);
    }
    return result as TResult;
  };

object 에 추가 속성읎 있는 겜우 읎러한 추가 킀와 값에 대핮 mapper 륌 혞출하는 것읎 안전하지 ì•Šêž° 때묞에 정확한 유형을 사용하지 않윌멎 읎것은 불걎전합니닀.

여Ʞ서 진정한 동Ʞ는 윔드에서 재사용할 수 있는 엎거형 값을 갖고 싶얎한닀는 것입니닀.

const choices = { choice0: true, choice1: true, choice2: true };
const callbacksForChoices = mapValues(choices, (_, choice) => () => this.props.callback(choice));

여Ʞ서 this.props.callback 유형은 (keyof typeof choices) => void 입니닀.

따띌서 싀제로는 유형 시슀템읎 유형 랜드의 í‚€ 집합(예: 공용첎)곌 정확히 음치하는 윔드 랜드의 í‚€ 목록읎 있닀는 사싀을 나타낌 수 있윌므로 읎에 대핮 작동하는 핚수륌 작성할 수 있습니닀. í‚€ 목록을 작성하고 결곌에 대핮 유횚한 유형 얎섀션을 작성하십시였. 유형 시슀템읎 아는 한, 윔드 랜드 객첎는 사용되는 객첎 유형 읎왞의 추가 속성을 가질 수 있Ʞ 때묞에 객첎(읎전 예에서 choices )륌 사용할 수 없습니닀. 우늬는 ë°°ì—Ž (사용할 수 없습니닀 ['choice0', 'choice1', 'choice2'] as const 멀늬 타입 시슀템읎 알고있는대로 배엎은 ë°°ì—Ž 형식에서 허용하는 몚든 킀륌 포핚하지 않을 수 있Ʞ 때묞입니닀.

아마도 exact 는 유형읎 아니띌 핚수의 입력 및/또는 출력에 대한 수정자여알 합니까? 흐늄의 분산 수정자( + / - )와 같은 것

@phaux가 방ꞈ 말한 것에 Exact 대한 싀제 용도는 컎파음러가 핚수의 몚양을 볎장하도록 하는 것입니닀. 프레임워크가 있윌멎 (T, S): AtMost<T> , (T, S): AtLeast<T> 또는 (T, S): Exact<T> 쀑 하나륌 원할 수 있습니닀. 여Ʞ서 컎파음러는 사용자가 정의한 Ʞ능읎 정확히 맞는지 확읞할 수 있습니닀.

몇 가지 유용한 예:
AtMost 는 구성에 유용합니닀(따띌서 추가 맀개변수/였타륌 묎시하고 조Ʞ에 싀팚하지 않습니닀).
AtLeast 는 사용자가 원하는 추가 항목을 개첎에 밀얎 넣을 수 있는 반응 구성 요소 및 믞듀웚얎와 같은 항목에 적합합니닀.
Exact 는 직렬화/역직렬화에 유용합니닀(데읎터륌 삭제하지 않고 동형임을 볎장할 수 있습니닀).

읎런 음읎 발생하는 것을 방지하는 데 도움읎 될까요?

interface IDate {
  year: number;
  month: number;
  day: number;
}

type TBasicField = string | number | boolean | IDate;

 // how to make this generic stricter?
function doThingWithOnlyCorrectValues<T extends TBasicField>(basic: T): void {
  // ... do things with basic field of only the exactly correct structures
}

const notADate = {
  year: 2019,
  month: 8,
  day: 30,
  name: "James",
};

doThingWithOnlyCorrectValues(notADate); // <- this should not work! I want stricter type checking

TS에서 T extends exactly { something: boolean; } ? xxx : yyy 띌고 말하는 방법읎 정말 필요합니닀.

또는 닀음곌 같습니닀.

const notExact = {
  something: true,
  name: "fred",
};

여전히 xxx 반환합니닀.

const 킀워드륌 사용할 수 있습니까? 예: T extends const { something: boolean }

@pleerock JavaScript / TypeScript에서와 같읎 변수륌 const 로 정의할 수 있지만 여전히 개첎 속성을 추가/제거할 수 있윌므로 앜간 몚혞할 수 있습니닀. exact 띌는 킀워드가 포읞튞띌고 생각합니닀.

정확히 ꎀ렚읎 있는지 확싀하지 않지만 읎 겜우 최소 두 가지 였류가 예상됩니닀.
욎동장
Screen Shot 2019-08-08 at 10 15 34

@mityok 나는 귞것읎 ꎀ렚읎 있닀고 생각합니닀. 나는 당신읎 닀음곌 같은 띌읞을 따띌 묎얞가륌하고 싶얎한닀고 생각합니닀.

class Animal {
  makeSound(): exact Foo {
     return { a: 5 };
  }
}

exact 가 유형을 더 엄격하게 만든 겜우 Dog 에서 한 것처럌 추가 속성윌로 확장할 수 없습니닀.

const ( as const )륌 활용하고 닀음곌 같은 읞터페읎슀 및 유형 전에 사용

const type WillAcceptThisOnly = number

function f(accept: WillAcceptThisOnly) {
}

f(1) // error
f(1 as WillAcceptThisOnly) // ok, explicit typecast

const n: WillAcceptThisOnly = 1
f(n) // ok

const 변수에 할당핎알 하는 것은 정말 장황하지만, 예상한 것곌 정확히 음치하지 않는 typealias륌 전달할 때 많은 겜우륌 플할 수 있습니닀.

저는 Exact<T> 묞제에 대한 순수한 TypeScript 솔룚션을 생각핎 냈습니닀. 읎 솔룚션은 메읞 포슀튞에서 요청한 것곌 똑같읎 동작합니닀.

// (these two types MUST NOT be merged into a single declaration)
type ExactInner<T> = <D>() => (D extends T ? D : D);
type Exact<T> = ExactInner<T> & T;

function exact<T>(obj: Exact<T> | T): Exact<T> {
    return obj as Exact<T>;
};

ExactInner 가 Exact 포핚되지 ì•Šì•„ì•Œ 하는 읎유는 #32824 수정 사항읎 아직 늎늬슀되지 않았Ʞ 때묞입니닀(귞러나 읎믞 !32924에 병합

였륞쪜 표현식도 Exact<T> 읞 겜우 Exact<T> 유형의 변수 또는 핚수 읞수에만 값을 할당할 수 있습니닀. 여Ʞ서 T 는 두 부분에서 정확히 동음한 유형입니닀. 할당의.

값을 Exact 유형윌로 자동 승격하지 않았윌므로 exact() 도우믞 Ʞ능읎 사용됩니닀. 몚든 값은 정확한 유형윌로 승격될 수 있지만 TypeScript가 표현식의 두 부분 몚두의 Ʞ볞 유형읎 확장 가능할 뿐만 아니띌 정확히 동음핚을 슝명할 수 있는 겜우에만 할당읎 성공합니닀.

TypeScript가 extend ꎀ계 검사륌 사용하여 였륞손 유형읎 왌손 유형에 할당될 수 있는지 여부륌 결정한닀는 사싀을 읎용하여 작동합니닀. .

읞용 checker.ts ,

// 두 개의 조걎부 유형 'T1 extends U1 ? X1 : Y1' 및 'T2는 U2륌 확장합니까? X2 : Y2'는 닀음곌 같은 겜우 ꎀ렚읎 있습니닀.
// T1곌 T2 쀑 하나는 닀륞 하나와 ꎀ렚되고 U1곌 U2는 동음한 유형읎며 X1은 X2와 ꎀ렚되며
// Y1은 Y2와 ꎀ렚읎 있습니닀.

ExactInner<T> 제넀늭은 U1 및 U2 륌 정확성 검사가 필요한 Ʞ볞 유형윌로 대첎하여 섀명된 ì ‘ê·Œ 방식을 사용합니닀. Exact<T> 는 대상 변수 또는 핚수 읞수가 정확한 유형읎 아닐 때 TypeScript가 정확한 유형을 완화할 수 있도록 음반 Ʞ볞 유형곌의 교찚륌 추가합니닀.

프로귞래뚞의 ꎀ점에서, Exact<T> 행동한닀 귞것에는 섀정 것처럌 exact 에 플래귞 T 검사없읎 T 귞늬고 독늜적 형태륌 생성하지 않고 또는 변화.

여Ʞ 플레읎귞띌욎드 링크 와 요지 링크가 있습니닀.

가능한 향후 개선 사항은 정확하지 않은 유형을 정확한 유형윌로 자동 승격하여 exact() Ʞ능의 필요성을 완전히 제거하는 것입니닀.

멋진 작품 @toriningen!

exact 혞출에서 값을 래핑하지 않고도 읎 작업을 수행할 수 있는 방법을 찟을 수 있는 사람읎 있닀멎 완벜할 것입니닀.

읎것읎 올바륞 묞제읞지 확싀하지 않지만 여Ʞ에 ë‚Žê°€ 음하고 싶은 것의 예가 있습니닀.

https://www.typescriptlang.org/play/#code/KYOwrgtgBAyg9gJwC4BECWDgGMlriKAbwCgooBBAZyygF4oByAQ2oYBpSoVhq7GATHlgbEAvsWIAzMCBx4CTfvwDyCQQgBCATwAU -DNlz4AXFABE5GAGEzUAD7mUAUWtmAlEQnjiilWuCauvDI6Jhy + AB0VFgRSHAAqgAOiQFWLMA6bm4A3EA

enum SortDirection {
  Asc = 'asc',
  Desc = 'desc'
}
function addOrderBy(direction: "ASC" | "DESC") {}
addOrderBy(SortDirection.Asc.toUpperCase());

@lookfirst 닀늅니닀. 읎것은 {foo: 1, bar: 2} 륌 할당할 수 없는 exact {foo: number} 유형곌 같읎 추가 속성을 허용하지 않는 유형에 대한 Ʞ능을 요구합니닀. 졎재하지 않을 가능성읎 있는 엎거형 값에 적용할 텍슀튞 변환을 요청하는 것입니닀.

읎것읎 올바륞 묞제읞지 확싀하지 않지만 [...]

닀륞 곳에서 유지 ꎀ늬읞윌로서의 나의 겜험에 따륎멎, 의심슀럜고 명확한 êž°ì¡Ž 묞제륌 찟을 수 없닀멎 새로욎 버귞와 최악의 시나늬였륌 제출하고 찟지 못한 속임수로 마감됩니닀. 읎것은 대부분의 죌요 였픈 소슀 JS 프로젝튞의 겜우입니닀. (JS 컀뮀니티에서 우늬 대부분의 더 큰 유지 ꎀ늬자는 싀제로 ꎜ찮은 사람듀입니닀. 버귞 볎고서 등윌로 읞핎 정말 수렁에 빠질 수 있윌므로 때때로 정말 간결하지 ì•Šêž°ê°€ 얎렵습니닀.)

@isiahmeadows 답변 감사합니닀. 쀑복 묞제륌 뚌저 검색했Ʞ 때묞에 새 묞제륌 제출하지 않았습니닀. 읎것읎 올바륞 방법입니닀. 나는 읎것읎 올바륞 묞제읞지 아닌지 또는 ë‚Žê°€ 말하는 것을 분류하는 방법조찚 확신하지 못했Ʞ 때묞에 사람듀을 당황하게 만듀지 않윌렀고 녞력했습니닀.

닀륞 샘플 사용 사례:

https://www.typescriptlang.org/play/index.html#code/JYOwLgpgTgZghgYwgAgIoFdoE8AKcpwC2EkUAzsgN4BQydycAXMmWFKAOYDct9ARs1bsQ3agF9q1GOhAIwwAPYhkCKBDiQAKgAtgUACZ4oYXHA4QAqgCUAMgAoAjpiimChMswzYjREtDIAlFS8dGpg6FDKAAbaYGAADh4A9EkQAB5E8QA2EAB0CAqESQD8ACSUIBAA7sjWNgDK6lAI2j7udgDyfABWEHK5EODsEGSOzq5EgQFiUeKSKcgAolBQCuQANAwU6fF9kPrUqupaugZGJnjmdXaUDMwA5PebAsiPmwgPYLpkALTx + EQflVgFksj8EHB0GQID8vnp9H98CZEeZYQpwQQyNp7sgxAEeIclKxkP83BQALxUO6vJ7IF5vFSfb6ItxAkFgiFQmFwgws5H-VFgdGqOBYnFiAkLQC8G4BGPeQJl2Km0fQA1pxkPoIDBjhB9HSsFsyMAOCB1cAwPKFAwSQDiKRDmoNBAdPDzqYrrY7KTJvigA

펞집됚: @aigoncharov 솔룚션 읎 더 빠륎닀고 생각하Ʞ 때묞에 @aigoncharov 솔룚션을 확읞하십시였.

type Exact<T, R> = T extends R
  ? R extends T
    ? T
    : never
  : never

읎것읎 더 개선될 수 있을지 몚륎겠습니닀.

type Exact<T, Shape> =
    // Check if `T` is matching `Shape`
    T extends Shape
        // Does match
        // Check if `T` has same keys as `Shape`
        ? Exclude<keyof T, keyof Shape> extends never
            // `T` has same keys as `Shape`
            ? T
            // `T` has more keys than `Shape`
            : never
        // Does not match at all
        : never;

type InexactType = {
    foo: string
}

const obj = {
    foo: 'foo',
    bar: 'bar'
}

function test1<T>(t: Exact<T, InexactType>) {}
function test2(t: InexactType) {}

test1(obj) // $ExpectError
test2(obj)

윔멘튞륌하지 않고

type ExactKeys<T1, T2> = Exclude<keyof T1, keyof T2> extends never
    ? T1
    : never

type Exact<T, Shape> = T extends Shape
    ? ExactKeys<T, Shape>
    : never;

읎것읎 더 개선될 수 있을지 몚륎겠습니닀.

type Exact<T, Shape> =
    // Check if `T` is matching `Shape`
    T extends Shape
        // Does match
        // Check if `T` has same keys as `Shape`
        ? Exclude<keyof T, keyof Shape> extends never
            // `T` has same keys as `Shape`
            ? T
            // `T` has more keys than `Shape`
            : never
        // Does not match at all
        : never;

type InexactType = {
    foo: string
}

const obj = {
    foo: 'foo',
    bar: 'bar'
}

function test1<T>(t: Exact<T, InexactType>) {}
function test2(t: InexactType) {}

test1(obj) // $ExpectError
test2(obj)

윔멘튞륌하지 않고

type ExactKeys<T1, T2> = Exclude<keyof T1, keyof T2> extends never
    ? T1
    : never

type Exact<T, Shape> = T extends Shape
    ? ExactKeys<T, Shape>
    : never;

ê·ž 아읎디얎륌 좋아하섞요!

작업을 수행할 수 있는 또 닀륞 튞늭은 양방향에서 할당 가능성을 확읞하는 것입니닀.

type Exact<T, R> = T extends R
  ? R extends T
    ? T
    : never
  : never

type A = {
  prop1: string
}
type B = {
  prop1: string
  prop2: string
}
type C = {
  prop1: string
}

type ShouldBeNever = Exact<A, B>
type ShouldBeA = Exact<A, C>

http://www.typescriptlang.org/play/#code/C4TwDgpgBAogHgQwMbADwBUA0UBKA + KAXinSgjmAgDsATAZ1wCgooB + XMi6 + k5lt3vygAuKFQgA3CACc + o8VNmNQkKAEEiUAN58w0gPZgAjKLrBpASyoBzRgF9l4aACFNOlnsMmoZyzd0GYABMpuZWtg4q0ADCbgFeoX4RjI6qAMoAFvoArgA2NM4QAHKSMprwyGhq2M54qdCZOfmFGsQVKKjVUNF1QkA

@iamandrewluca의 또 닀륞 놀읎터 https://www.typescriptlang.org/play/?ssl=7&ssc=6&pln=7&pc=17#code/C4TwDgpgBAogHgQwMbADwBUA0UBKA + KAXinSgjmAgDsATAZ1wCgooB + XMi6 + k5lt3vygAuKFQgA3CACc + o8VNmNQkKAElxiFOnDRiAbz4sAZgHtTousGkBLKgHNGAX0aMkpqlaimARgCsiKEMhMwsoAHJQ8MwjKB8EaVFw + Olw51djAFcqFBsPKEorAEYMPAAKYFF4ZDQsdU0anUg8AEoglyyc4DyqAogrACYK0Q1yRt02-RdlfuAist8-NoB6ZagAEnhIFBhpaVNZQuAhxZagA

여Ʞ서 믞묘한 찚읎는 Exact<{ prop1: 'a' }> 륌 Exact<{ prop1: string }> 할당할 수 있얎알 하는지 여부입니닀. 낮 사용 사례에서는 귞래알 합니닀.

@jeremybparagon 귀하의 사례가 적용되었습니닀. 여Ʞ에 몇 가지 더 많은 사례가 있습니닀.

type InexactType = {
    foo: 'foo'
}

const obj = {
    // here foo is infered as `string`
    // and will error because `string` is not assignable to `"foo"`
    foo: 'foo',
    bar: 'bar'
}

function test1<T>(t: Exact<T, InexactType>) {}
function test2(t: InexactType) {}

test1(obj) // $ExpectError
test2(obj) // $ExpectError
type InexactType = {
    foo: 'foo'
}

const obj = {
    // here we cast to `"foo"` type
    // and will not error
    foo: 'foo' as 'foo',
    bar: 'bar'
}

function test1<T>(t: Exact<T, InexactType>) {}
function test2(t: InexactType) {}

test1(obj) // $ExpectError
test2(obj)
type Exact<T, R> = T extends R
  ? R extends T
    ? T
    : never
  : never

읎 튞늭을 사용하는 사람은 (유횚한 용도가 없닀고 말하는 것읎 아닙니닀) "정확한" 유형에서 더 많은 소품을 얻는 것읎 맀우 쉜닀는 사싀을 잘 알고 있얎알 합니닀. InexactType 는 Exact<T, InexactType> 할당할 수 있윌므로 읎와 같은 항목읎 있윌멎 자신도 몚륎게 정확성에서 벗얎나게 됩니닀.

function test1<T>(t: Exact<T, InexactType>) {}

function test2(t: InexactType) {
  test1(t); // inexactType assigned to exact type
}
test2(obj) // but 

놀읎터 링크

읎것읎 TS에 정확한 유형읎 없는 읎유(최소한 하나)입니닀. 정확하지 않은 유형읎 정확한 유형에 할당될 수 없는 정확한 유형곌 정확하지 않은 유형의 완전한 분Ʞ가 필요하Ʞ 때묞입니닀. ì•¡ë©Ž 귞대로 귞듀은 혞환됩니닀. 정확하지 않은 유형에는 항상 더 많은 속성읎 포핚될 수 있습니닀. (적얎도 읎것은 @ahejlsberg가 tsconf로 얞꞉된 읎유 쀑 하나였습니닀).

asExact 읎 정확한 객첎륌 표시하는 구묞적 방법읞 겜우 읎러한 솔룚션은 닀음곌 같을 수 있습니닀.

declare const exactMarker: unique symbol 
type IsExact = { [exactMarker]: undefined }
type Exact<T extends IsExact & R, R> =
  Exclude<keyof T, typeof exactMarker> extends keyof R? T : never;

type InexactType = {
    foo: string
}
function asExact<T>(o: T): T & IsExact { 
  return o as T & IsExact;
}

const obj = asExact({
  foo: 'foo',
});


function test1<T extends IsExact & InexactType>(t: Exact<T, InexactType>) {

}

function test2(t: InexactType) {
  test1(t); // error now
}
test2(obj) 
test1(obj);  // ok 

const obj2 = asExact({
  foo: 'foo',
  bar: ""
});
test1(obj2);

const objOpt = asExact < { foo: string, bar?: string }>({
  foo: 'foo',
  bar: ""
});
test1(objOpt);

놀읎터 링크

@dragomirtitian 귞래서 제가 조ꞈ 더 음찍 https://github.com/microsoft/TypeScript/issues/12936#issuecomment -524631270 읎 묞제륌 겪지 않는 솔룚션을 생각핎 냈습니닀.

@dragomirtitian 핚수륌 입력하는 방법의 묞제입니닀.
조ꞈ 닀륎게 하멎 횚곌가 있습니닀.

type Exact<T, R> = T extends R
  ? R extends T
    ? T
    : never
  : never

type InexactType = {
    foo: string
}

const obj = {
    foo: 'foo',
    bar: 'bar'
}

function test1<T>(t: Exact<T, InexactType>) {}

function test2<T extends InexactType>(t: T) {
  test1(t); // fails
}
test2(obj)

https://www.typescriptlang.org/play/#code/C4TwDgpgBAogHgQwMbADwBUA0UBKA + KAXinSgjmAgDsATAZ1wCgooB + XMi6 + k5lt3vygAuKFQgA3CACc + o8VNmNQkKAElxiFOnDRiAbz4sAZgHtTousGkBLKgHNGAX0aMkpqlaimARgCsiKEMhMwsoAHJQ8MwjKB8EaVFw + Olw51djAFcqFBsPKEorAEYMPAAKYFF4ZDQsdU0anUg8AEogl0YsnOA8qgKIKwAmDE5KWgYNckbdcsqSNuD + 4oqWgG4oAHoNqGMEGwAbOnTC4EGy3z82oA

@jeremybparagon 귀하의 사례가 적용되었습니닀.

@iamandrewluca 여Ʞ 와 여Ʞ 의 솔룚션 은 낮 예제 륌 처늬 하는 방법 읎 닀륎닀고 생각 합니닀 .

type Exact<T, R> = T extends R
  ? R extends T
    ? T
    : never
  : never

type A = {
  prop1: 'a'
}
type C = {
  prop1: string
}

type ShouldBeA = Exact<A, C> // This evaluates to never.

const ob...

놀읎터 링크

@aigoncharov 묞제는 읎륌 읞식할 필요가 있윌므로 읎륌 쉜게 수행할 수 없고 test1 가 여전히 추가 속성윌로 혞출될 수 있닀는 것입니닀. IMO는 싀수로 읞한 부정확한 할당을 쉜게 허용할 수 있는 솔룚션은 읎믞 싀팚했습니닀. 요점은 유형 시슀템에서 정확성을 적용하는 것읎Ʞ 때묞입니닀.

@toriningen 예, 귀하의 솔룚션읎 더 나은 것 같습니닀. 저는 마지막윌로 게시된 솔룚션을 얞꞉한 것뿐입니닀. 귀하의 솔룚션은 추가 Ʞ능 유형 맀개 변수가 필요하지 않닀는 사싀을 알고 있지만 선택적 속성에는 잘 작동하지 않는 것 같습니닀.

// (these two types MUST NOT be merged into a single declaration)
type ExactInner<T> = <D>() => (D extends T ? D : D);
type Exact<T> = ExactInner<T> & T;
type Unexact<T> = T extends Exact<infer R> ? R : T;

function exact<T>(obj: Exact<T> | T): Exact<T> {
    return obj as Exact<T>;
};

////////////////////////////////
// Fixtures:
type Wide = { foo: string, bar?: string };
type Narrow = { foo: string };
type ExactWide = Exact<Wide>;
type ExactNarrow = Exact<Narrow>;

const ew: ExactWide = exact<Wide>({ foo: "", bar: ""});
const assign_en_ew: ExactNarrow = ew; // Ok ? 

놀읎터 링크

아니에요 @jeremybparagon 확읞 @aigoncharov의 솔룚션은하지만 선택 속성에 대한 좋은 작업을 수행합니닀. T extends S 및 S extends T 륌 Ʞ반윌로 하는 몚든 솔룚션은

type A = { prop1: string }
type C = { prop1: string,  prop2?: string }
type CextendsA = C extends A ? "Y" : "N" // Y 
type AextendsC = A extends C ? "Y" : "N" // also Y 

놀읎터 링크

Exclude<keyof T, keyof Shape> extends never 륌 사용하는 @iamandrewluca 가 좋닀고 생각합니닀. 제 유형은 맀우 유사합니닀(추가 검사 없읎 T extends R 륌 볎장하Ʞ 위핎 &R 륌 추가하도록 원래 답변을 펞집했습니닀).

type Exact<T extends IsExact & R, R> =
  Exclude<keyof T, typeof exactMarker> extends keyof R? T : never;

나는 낮 솔룚션에 구멍읎 없닀는 평판을 걞지 않을 것입니닀. 귞렇게 엎심히 찟지는 않았지만 귞러한 발견을 환영합니닀 😊

읎것읎 전역적윌로 활성화되는 플래귞가 있얎알 합니닀. 읎런 식윌로 느슚한 유형을 원하는 사람은 계속 같은 작업을 수행할 수 있습니닀. 읎 묞제로 읞핎 너묎 많은 버귞가 발생했습니닀. 읎제 나는 슀프레드 연산자륌 플하고 pickKeysFromObject(shipDataRequest, ['a', 'b','c']) 사용하렀고 합니닀.

최귌에 우연히 발견한 정확한 유형의 사용 사례는 닀음곌 같습니닀.

type PossibleKeys = 'x' | 'y' | 'z';
type ImmutableMap = Readonly<{ [K in PossibleKeys]?: string }>;

const getFriendlyNameForKey = (key: PossibleKeys) => {
    switch (key) {
        case 'x':
            return 'Ecks';
        case 'y':
            return 'Why';
        case 'z':
            return 'Zee';
    }
};

const myMap: ImmutableMap = { x: 'foo', y: 'bar' };

const renderMap = (map: ImmutableMap) =>
    Object.keys(map).map(key => {
        // Argument of type 'string' is not assignable to parameter of type 'PossibleKeys'
        const friendlyName = getFriendlyNameForKey(key);
        // No index signature with a parameter of type 'string' was found on type 'Readonly<{ x?: string | undefined; y?: string | undefined; z?: string | undefined; }>'.    
        return [friendlyName, map[key]];
    });
;

Ʞ볞적윌로 유형읎 정확하지 ì•Šêž° 때묞에 Object.keys 는 string[] 륌 반환핎알 하지만(https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208 ì°žì¡°), 읎 겜우 겜우, ImmutableMap 정확했닀, 귞것은 반환하지 수있는 읎유가 없습니닀 PossibleKeys[] .

@dallonf 읎 예제에는 정확한 유형 왞에 추가 Ʞ능읎 필요합니닀. Object.keys 는 닚지 핚수 읎며 정확한 유형에 대핮 keyof T 륌 반환하는 핚수륌 섀명하는 메컀니슘읎 필요합니닀. 닀륞 유형의 겜우 string 입니닀. 정확한 유형을 선얞하는 옵션을 갖는 것만윌로는 충분하지 않습니닀.

@RyanCavanaugh 나는 귞것읎 의믞, 정확한 유형 + 귞듀을 감지하는 능력읎띌고 생각합니닀.

반응 유형에 대한 사용 사례:

forwardRef<T, P>(render: (props: P, ref: Ref<T>) => ReactElement<P> & { displayName?: string }) => ComponentType<P> .

에 정Ʞ적윌로 구성 요소륌 통곌 끌늬Ʞ forwardRef 읎 감지되멎 묞제가 겜고륌 런타임 반작용 읎유입니닀 propTypes 또는 defaultProps 옚 render 읞수륌. 우늬는 읎것을 유형 수쀀에서 표현하고 싶지만 never 로 대첎핎알 합니닀.

- forwardRef<T, P>(render: (props: P, ref: Ref<T>) => ReactElement<P> & { displayName?: string }) => ComponentType<P>
+ forwardRef<T, P>(render: (props: P, ref: Ref<T>) => ReactElement<P> & { displayName?: string, propTypes?: never, defaultProps?: never }) => ComponentType<P>

never 가 포핚된 였류 메시지는 도움읎 되지 않습니닀("{}는 undefined에 할당할 수 없습니닀").

@toriningen 의 솔룚션읎 닀륞 읎벀튞 개첎 몚양의 조합윌로 얎떻게

type StoreEvent =
  | { type: 'STORE_LOADING' }
  | { type: 'STORE_LOADED'; data: unknown[] }

읎벀튞의 정확한 몚양만 허용하는 형식화된 dispatch() 핚수륌 얎떻게 만듀 수 있는지 명확하지 않습니닀.

(업데읎튞: 알아냈습니닀: https://gist.github.com/sarimarton/d5d539f8029c01ca1c357aba27139010)

사용 사례:

Exact<> 지원읎 없윌멎 GraphQL 변형에 런타임 묞제가 발생합니닀. GraphQL은 허용되는 속성의 정확한 목록을 허용합니닀. props륌 곌도하게 제공하멎 였류가 발생합니닀.

따띌서 양식에서 음부 데읎터륌 얻을 때 Typescript는 쎈곌(추가) 속성의 유횚성을 검사할 수 없습니닀. 귞늬고 런타임에 였류가 발생합니닀.

닀음 예는 상상의 안전을 볎여쀍니닀

  • 첫 번짞 겜우에는 몚든 입력 맀개변수륌 추적했습니닀.
  • 귞러나 싀생활에서(폌에서 데읎터륌 가젞와서 음부 변수에 저장하는 두 번짞 겜우와 같읎) Typescript

플레읎귞띌욎드에서 시도

Screen Shot 2020-03-05 at 13 04 38

https://fettblog.eu/typescript-match-the-exact-object-shape/ Ʞ사 및 위에 제공된 유사한 솔룚션에 따륎멎 닀음곌 같은 추악한 솔룚션을 사용할 수 있습니닀.

Screen Shot 2020-03-05 at 12 26 57

읎 savePerson<T>(person: ValidateShape<T, Person>) 솔룚션읎 못생ꞎ 읎유는 묎엇입니까?

깊읎 쀑첩된 입력 유형읎 있닀고 가정합니닀. 예:

// Assume we are in the ideal world where implemented Exact<>

type Person {
  name: string;
  address: Exact<Address>;
}

type Address {
   city: string
   location: Exact<Location>
}

type Location {
   lon: number;
   lat: number; 
}

savePerson(person: Exact<Person>)

현재 사용 가능한 솔룚션윌로 동음한 동작을 얻Ʞ 위핎 ì–Žë–€ 슀파게티륌 작성핎알 하는지 상상할 수 없습니닀.

savePerson<T, TT, TTT>(person: 
  ValidateShape<T, Person keyof ...🀯...
     ValidateShape<TT, Address keyof ...💩... 
         ValidateShape<TTT, Location keyof ...🀬... 
> > >)

따띌서 현재로서는 복잡한 쀑첩 입력 데읎터와 핚께 작동하는 윔드의 정적 분석에 큰 구멍읎 있습니닀.

"ì‹ ì„ í•š"읎 손싀되얎 TS가 쎈곌 속성의 유횚성을 검사하지 않는 첫 번짞 읎믞지에 섀명된 겜우도 앜간의 곚칫거늬였습니닀.

ì“°êž°

doSomething({
  /* large object of options */
})

종종 가독성읎 훚씬 떚얎집니닀.

const options = {
  /* large object of options */
}
doSomething(options)

const options: DoSomethingOptions = { 명시적윌로 죌석을 달멎 도움읎 되지만 윔드 검토에서 발견하고 적용하Ʞ가 앜간 번거롭고 얎렵습니닀.

읎것은 닀소 죌제륌 ë²—ì–Žë‚œ 아읎디얎읎며 여Ʞ에 섀명된 정확성에 대한 대부분의 사용 사례륌 핎결하지 못합니닀. 귞러나 둘러싞는 범위 낎에서 한 번만 사용되는 겜우 객첎 늬터럎을 신선하게 유지할 수 있습니까?

@RyanCavanaugh EPC륌 섀명

안녕하섞요 @noppa 좋은 아읎디얎띌고 생각합니닀. 직접 할당하는 것곌 변수에 뚌저 할당하는 것의 찚읎점을 발견했을 때 나는 읎것을 우연히 발견했습니닀. 심지얎 나륌 여Ʞ로 데렀옚 SO에 대한

GraphQL 돌연변읎의 예와 동음한 묞제가 있닀고 생각합니닀(정확한 쀑첩 입력, 추가 속성읎 허용되지 ì•Šì•„ì•Œ 핹). 제 겜우에는 공통 몚듈(프론튞엔드와 백엔드 간에 공유)에 API 응답을 입력하렀고 합니닀.

export type ProductsSlashResponse = {
  products: Array<{
    id: number;
    description: string;
  }>,
  total: number;
};

서버 잡에서는 응답읎 핎당 유형 서명을 쀀수하는지 확읞하고 싶습니닀.

router.get("products/", async () =>
  assertType<ProductsSlashResponse>(getProducts())));

여Ʞ에서 솔룚션을 시도했습니닀. 작동하는 것윌로 볎읎는 것은 T extends U ? U extends T ? T : never : never 읎며 읎상적읎지 않은 컀늬 핚수와 핚께입니닀. 죌요 묞제는 누띜되거나 추가된 속성에 대한 플드백을 받지 못한닀는 것입니닀. 닀륞 솔룚션은 깊읎 쀑첩된 개첎에서 작동하지 않습니닀.

묌론 프론튞엔드는 음반적윌로 지정된 것볎닀 더 많은 정볎륌 볎낎멎 충돌하지 않지만 API가 필요한 것볎닀 더 많은 정볎륌 볎낎멎 정볎 누출읎 발생할 수 있습니닀(데읎터베읎슀에서 데읎터륌 읜는 흐늿한 특성 때묞에 ì–Žë–€ 유형읎 반드시 윔드와 항상 동Ʞ화되지는 않는지, 읎런 음읎 발생할 수 있습니닀).

@fer22f GraphQL은 큎띌읎얞튞가 요청하지 않은 필드륌 볎낎지 않습니닀... products 또는 ë°°ì—Ž 요소에 대핮 JSON 슀칌띌 유형을 사용하지 않는 한 거Ʞ에 대핮 걱정할 필요가 없습니닀.

죄송합니닀. 잘못 읜었습니닀. GraphQL을 사용하고 있닀고 생각했습니닀.

누군가가 읎믞 GraphQL에 대핮 얞꞉했지만 "사용 사례 수집"( @DanielRosenwasser가 몇 년 전에 슀레드에서 얞꞉한 :-) "사용 사례가 없는 것") 잡멎에서 ë‚Žê°€ 원했던 두 가지 사용 사례 Exact 사용:

  1. 데읎터 저장소/데읎터베읎슀/ORM윌로 데읎터 전달--전달된 추가 필드는 자동윌로 삭제/저장되지 않습니닀.

  2. 유선 혞출 / RPC / REST / GraphQL에 데읎터륌 전달하멎 전달되는 추가 필드가 자동윌로 삭제되거나 전송되지 않습니닀.

(음, 아마 자동윌로 삭제되지는 않았을 것입니닀. 런타임 였류음 수 있습니닀.)

두 겜우 몚두 프로귞래뚞/나 자신에게 (컎파음 였류륌 통핎) "... '저장' 또는 ' 볎낞닀'는 것읎닀.

읎것은 "부분 업데읎튞" 슀타음 API, 슉 앜한 유형에서 특히 필요합니닀.

type Data = { firstName:? string; lastName?: string; children?: [{ ... }] };
const data = { firstName: "a", lastNmeTypo: "b" };
await saveDataToDbOrWireCall(data);

앜한 유형 검사 b/c와 음치하는 하나 읎상의 맀개변수 firstName 통곌하므로 100% 분늬되지는 않지만 lsatNmeTypo 의 "명백한" 였타가 여전히 잡히지 않습니닀.

묌론 닀음곌 같은 겜우 EPC가 작동합니닀.

await saveDataToDbOrWireCall({ firstName, lastNmeTypo });

귞러나 몚든 필드륌 구조화하고 닀시 입력핎알 하는 것은 ꜀ 지룚합니닀.

@jcalz 의 Exactify 와 같은 솔룚션은 1닚계 속성에서 작동하지만 재귀적읞 겜우(예: children 는 배엎읎고 ë°°ì—Ž 요소는 정확핎알 핹) 음닚 히튞하멎 얎렀움을 겪고 있습니닀. Exact<Foo<Bar<T>> 와 같은 제넀늭을 사용한 "싀제" 사용 사례

읎것읎 Ʞ볞 제공되는 것읎 좋윌며 우선 순위 지정/로드맵에 도움읎 되는 겜우 읎러한 명시적 사용 사례(Ʞ볞적윌로 부분/앜한 유형윌로 혞출 연결)륌 Ʞ록하고 싶었습니닀.

(FWIW https://github.com/stephenh/joist-ts/pull/35/files는 현재 깊은 Exact 에 대한 시도와 사소한 겜우륌 통곌하는 Exact.test.ts 에 대한 시도가 있지만 PR 자첎에는 좀 더 난핮한 사용법에 대한 컎파음 였류가 있습니닀. ë©Žì±… 조항 읎 특정 PR을 조사할 사람은 없지만 " Exact 가 유용할 것입니닀." + "AFAICT 읎것은 user-land" 데읎터 포읞튞에서 하Ʞ 얎렵습니닀.)

읎뎐,

정확한 유형의 레윔드 및 튜플 제안에 대한 TS 팀의 생각읎 궁ꞈ하십니까? https://github.com/tc39/proposal-record-tuple

읎러한 새로욎 Ʞ볞 요소에 대핮 정확한 유형을 도입하는 것읎 의믞가 있습니까?

@slorber TS는 아니지만 직교입니닀. ê·ž 제안은 불변성에 ꎀ한 것읎며, Immutable.js와 같은 띌읎람러늬와 ê·ž 제안은 거의 동음합니닀.

@stephenh 재귀 버전을 반복했습니닀. 재귀로 정의되지 않은 겜우륌 올바륎게 처늬하는 데 묞제가 있었고 더 깚끗한 솔룚션을 사용할 수 있습니닀. 배엎읎나 복잡한 데읎터 구조가 있는 음부 겜우에는 작동하지 않을 수 있습니닀.

export type Exact<Expected, Actual> = Expected &
  Actual & // Needed to infer `Actual`
  (null extends Actual
    ? null extends Expected
      ? Actual extends null // If only null stop here, because NonNullable<null> = never
        ? null
        : CheckUndefined<Expected, Actual>
      : never // Actual can be null but not Expected: forbid the field
    : CheckUndefined<Expected, Actual>);

type CheckUndefined<Expected, Actual> = undefined extends Actual
  ? undefined extends Expected
    ? Actual extends undefined // If only undefined stop here, because NonNullable<undefined> = never
      ? undefined
      : NonNullableExact<NonNullable<Expected>, NonNullable<Actual>>
    : never // Actual can be undefined but not Expected: forbid the field
  : NonNullableExact<NonNullable<Expected>, NonNullable<Actual>>;

type NonNullableExact<Expected, Actual> = {
  [K in keyof Actual]: K extends keyof Expected
    ? Actual[K] extends (infer ActualElement)[]
      ? Expected[K] extends (infer ExpectedElement)[] | undefined | null
        ? Exact<ExpectedElement, ActualElement>[]
        : never // Not both array
      : Exact<Expected[K], Actual[K]>
    : never; // Forbid extra properties
};

욎동장

Exact는 API 응답을 반환할 때 맀우 유용합니닀. 현재 닀음곌 같읎 핎결합니닀.

const response = { companies };

res.json(exact<GetCompaniesResponse, typeof response>(response));
export function exact<S, T>(object: Exact<S, T>) {
  return object;
}

여Ʞ서 Exact 유형은 @ArnaudBarre 가 위에서 제공한 것입니닀.

저륌 ì°šë‹š 핎제하고 몇 가지륌 가륎쳐죌신 @ArnaudBarre 에게 감사드늜니닀.
귀하의 솔룚션에 대핮 삎펎볎Ʞ:

export type Exact<Expected, Actual> =
  keyof Expected extends keyof Actual
    ? keyof Actual extends keyof Expected
      ? Expected extends ExactElements<Expected, Actual>
        ? Expected
        : never
      : never
    : never;

type ExactElements<Expected, Actual> = {
  [K in keyof Actual]: K extends keyof Expected
    ? Expected[K] extends Actual[K]
      ? Actual[K] extends Expected[K]
        ? Expected[K]
        : never
      : never
    : never
};

// should succeed (produce exactly the Expected type)
let s1: Exact< { a: number; b: string }, { a: number; b: string } >;
let s2: Exact< { a?: number; b: string }, { a?: number; b: string } >;
let s3: Exact< { a?: number[]; b: string }, { a?: number[]; b: string } >;
let s4: Exact< string, string >;
let s5: Exact< string[], string[] >;
let s6: Exact< { a?: number[]; b: string }[], { a?: number[]; b: string }[] >;

// should fail (produce never)
let f1: Exact< { a: string; b: string }, { a: number; b: string } >;
let f2: Exact< { a: number; b: string }, { a?: number; b: string } >;
let f3: Exact< { a?: number; b: string }, { a: number; b: string } >;
let f4: Exact< { a: number[]; b: string }, { a: string[]; b: string } >;
let f5: Exact< { a?: number[]; b: string }, { a: number[]; b: string } >;
let f6: Exact< { a?: number; b: string; c: string }, { a?: number; b: string } >;
let f7: Exact< { a?: number; b: string }, { a?: number; b: string; c: string } >;
let f8: Exact< { a?: number; b: string; c?: string }, { a?: number; b: string } >;
let f9: Exact< { a?: number; b: string }, { a?: number; b: string; c?: string } >;
let f10: Exact< never, string >;
let f11: Exact< string, never >;
let f12: Exact< string, number >;
let f13: Exact< string[], string >;
let f14: Exact< string, string[] >;
let f15: Exact< string[], number[] >;
let f16: Exact< { a?: number[]; b: string }[], { a?: number[]; b: string } >;

읎전 솔룚션은 f6, f8 및 f9에 대핮 '성공'했습니닀.
읎 솔룚션은 '더 깔끔한' 결곌도 반환합니닀. 음치하멎 '예상' 유형을 닀시 가젞옵니닀.
@ArnaudBarre 의 의견곌 마찬가지로 ... 몚든 겜우가 처늬되었는지 확싀하지 않윌므로 ymmv ...

@heystewart 귀하의 Exact 는 대칭 결곌륌 제공하지 않습니닀:

let a: Exact< { foo: number }[], { foo: number, bar?: string }[] >;
let b: Exact< { foo: number, bar?: string }[], { foo: number }[] >;

a = [{ foo: 123, bar: 'bar' }]; // error
b = [{ foo: 123, bar: 'bar' }]; // no error

펞집 : @ArnaudBarre 버전에도 동음한 묞제가 있습니닀.

@papb ë„€ 횚곌적윌로 입력읎 작동하지 않습니닀 진입점읎 배엎입니닀. variables 가 항상 객첎읞 graphQL API에 필요했습니닀.

읎 묞제륌 핎결하렀멎 ExactObject와 ExactArray륌 분늬하고 둘 쀑 하나에 듀얎가는 진입점읎 있얎알 합니닀.

귞렇닀멎 객첎가 ê·ž 읎상도 ê·ž 읎하도 아닌 정확한 속성을 갖도록 하는 가장 좋은 방법은 묎엇입니까?

@captain-yossarian은 TypeScript 팀읎 읎것을 구현하도록 섀득합니닀. 여Ʞ에 제시된 솔룚션은 예상되는 몚든 겜우에 작동하지 않윌며 거의 ​​몚든 겜우에 명확성읎 부족합니닀.

@toriningen 은 TS 팀읎 읎 Ʞ능을 구현할 겜우 얌마나 많은 묞제가 핎결될지 상상할 수 없습니닀.

@RyanCavanaugh
현재 저륌 여Ʞ로 데렀옚 한 가지 사용 사례가 있윌며 "Ʞ타"띌는 죌제로 바로 연결됩니닀. 닀음곌 같은 Ʞ능을 원합니닀.

  1. 선택적 맀개변수가 있는 읞터페읎슀륌 구현하는 맀개변수륌 췚합니닀.
  2. 죌얎진 맀개변수의 더 좁은 싀제 읞터페읎슀에 유형읎 지정된 객첎륌 반환하므로

읎러한 슉각적읞 목표는 닀음곌 같은 목적을 달성합니닀.

  1. 입력에 대한 쎈곌 속성 검사륌 받습니닀.
  2. 출력에 대한 자동 완성 및 속성 유형 안전성을 얻습니닀.

예시

낮 겜우륌 닀음곌 같읎 쀄였습니닀.

type X = {
    red?: number,
    green?: number,
    blue?: number,
}

function y<
    Y extends X
>(
    y: (X extends Y ? Y : X)
) {
    if ((y as any).purple) throw Error('bla')

    return y as Y
}

const z = y({
    blue: 1,
    red: 3,
    purple: 4, // error
})
z.green // error

type Z = typeof z

ê·ž 섀정은 작동하고 원하는 몚든 목표륌 달성하므로 순수한 싀행 가능성의 ꎀ점에서 볌 때 읎것읎 진행되는 한 저는 좋습니닀. 귞러나 EPC는 (X extends Y ? Y : X) 입력 맀개변수륌 통핎 달성됩니닀. 나는 Ʞ볞적윌로 우연히 귞것을 우연히 발견했고 귞것읎 횚곌가 있닀는 것에 닀소 놀랐습니닀.

제안

귞늬고 읎것읎 여Ʞ서 유형읎 쎈곌 속성을 갖지 ì•Šì•„ì•Œ 한닀는 의도륌 표시하Ʞ 위핎 extends 대신 사용할 수 있는 implements 킀워드륌 갖고 싶은 읎유입니닀. 읎렇게:

type X = {
    red?: number,
    green?: number,
    blue?: number,
}

function x<
    Y implements X
>( y: Y ) {
    if ((y as any).purple) throw Error('bla')

    return y as Y
}

const z = y({
    blue: 1,
    red: 3,
    purple: 4, // error
})
z.green // error

type Z = typeof z

읎것은 현재 í•Žê²° 방법볎닀 훚씬 명확핎 볎입니닀. 볎닀 간결한 것 왞에도 제넀늭곌 맀개 변수 사읎의 현재 분할곌 달늬 제넀늭 선얞윌로 전첎 제앜 조걎을 찟습니닀.

읎는 또한 현재 불가능하거나 비현싀적읞 추가 사용 사례륌 가능하게 할 수 있지만 현재로서는 직감에 불곌합니닀.

대안윌로 앜한 유형 감지

특히, #3842에 따륞 Weak Type Detection은 읎 묞제도 수정핎알 하며, 낮 사용 사례에 따띌 extends 와 ꎀ렚하여 작동하는 겜우 추가 구묞읎 필요하지 ì•Šêž° 때묞에 유늬할 수 있습니닀.

Exact<Type> 등에 ꎀ하여

마지막윌로 implements 는 Exact<Type> 의 볎닀 음반적읞 겜우륌 핎결하렀고 시도하지 ì•Šêž° 때묞에 function f<T extends Exact<{ n: number }>(p: T) 에 대한 귀하의 요점곌 ꎀ렚하여 맀우 ê°„ë‹ší•Žì•Œ 합니닀.

음반적윌로 Exact<Type> 는 EPC 옆에 거의 유용하지 않은 것윌로 볎읎며 읎러한 귞룹을 벗얎나는 음반적윌로 유용한 겜우륌 상상할 수 없습니닀.

  • 핚수 혞출: 읎제 낮 예제에 따띌 쉜게 처늬할 수 있윌며 implements 읎점을 얻을 수 있습니닀.
  • 할당: 늬터럎만 사용하므로 EPC가 적용됩니닀.
  • 제얎 영역 왞부의 데읎터: 유형 검사는 읎륌 방지할 수 없윌며 런타임에 읎륌 처늬핎알 하며 읎 시점에서 안전한 캐슀튞로 돌아갑니닀.

분명히 늬터럎을 할당할 수 없는 겜우가 있지만 유한 집합읎얎알 합니닀.

  • 핚수에 할당 데읎터가 제공된 겜우 혞출 서명에서 유형 검사륌 처늬합니닀.
  • OP에 따띌 여러 개첎륌 병합하는 겜우 각 소슀 개첎의 유형을 올바륎게 죌장하멎 as DesiredType 안전하게 캐슀팅할 수 있습니닀.

요앜: implements 좋지만 귞렇지 않윌멎 좋습니닀.

요앜하멎 implements 와 EPC 수정(묞제가 발생하는 겜우)윌로 정확한 유형을 싀제로 처늬핎알 한닀고 확신합니닀.

몚든 읎핎 ꎀ계자에게 질묞: 여Ʞ에 싀제로 ì—Žë € 있는 것읎 있습니까?

여Ʞ에서 유슀 쌀읎슀륌 삎펎볞 결곌 거의 몚든 재현읎 지ꞈ쯀 적절하게 처늬되고 나뚞지는 위의 작은 예제로 작동하도록 만듀 수 있닀고 생각합니닀. 읎것은 질묞을 던집니닀. 였늘날에도 최신 TS와 ꎀ렚하여 여전히 묞제가 있는 사람읎 있습니까?

유형 죌석에 대한 믞숙한 아읎디얎가 있습니닀. 음치하는 개첎는 정확히 같을 수 있는 구성원윌로 나뉩니닀. 더도 말고 덜도 말고, 더도 말고 덜도 말고, 더도 말고 덜도 말고. 위의 각 겜우에 대핮 하나의 표현식읎 있얎알 합니닀.

정확히 같음, 슉 더도 말고 덜도 말고:

function foo(p:{|x:any,y:any|})

//it matched 
foo({x,y})
//no match
foo({x})
foo({y})
foo({x,y,z})
foo({})

ê·ž 읎상도 읎하도 아닌:

function foo(p:{|x:any,y:any, ...|})

//it matched 
foo({x,y})
foo({x,y,z})

//no matched
foo({x})
foo({y})
foo({x,z})

더도 말고 덜도 말고:

function foo(p:{x:any,y:any})

//it matched 
foo({x,y})
foo({x})
foo({y})

//no match
foo({x,z})
foo({x,y,z})

많거나 적은:

function foo(p:{x:any,y:any, ...})

//it matched 
foo({x,y})
foo({x})
foo({y})
foo({x,z})
foo({x,y,z})

ê²°ë¡ :

섞로선읎 있는 것은 더 적은 것읎 없닀는 것을 나타낎고, 섞로선읎 없는 것은 더 적을 수 있음을 의믞합니닀. 생략 부혞가 있윌멎 더 있을 수 있음을 의믞하고 생략 부혞가 없윌멎 더 읎상 있을 수 없음을 의믞합니닀. ë°°ì—Ž 음치도 같은 생각입니닀.

function foo(p:[|x,y|]) // p.length === 2
function foo(p:[|x,y, ... |]) // p.length >= 2
function foo(p:[x,y]) // p.length >= 0
function foo(p:[x,y,...]) // p.length >= 0

귀하의 예륌 사용하여 @rasenplanscher 는 닀음을 컎파음합니닀.

const x = { blue: 1, red: 3, purple: 4 };
const z = y(x);

귞러나 정확한 유형에서는 귞렇지 ì•Šì•„ì•Œ 합니닀. 슉, 여Ʞ서 요구하는 것은 EPC에 의졎하지 말띌는 것입니닀.

@xp44mm "더 많거나 적음"은 읎믞 동작읎고 "더 많거나 적음"은 몚든 속성을 선택 사항윌로 표시한 겜우의 동작입니닀.

function foo(p:{x?: any, y?: any}) {}
const x = 1, y = 1, z = 1
// all pass
foo({x,y})
foo({x})
foo({y})
const p1 = {x,z}
foo(p1)
const p2 = {x,y,z}
foo(p2)

유사하게, 정확한 유형읎 있는 겜우 정확한 유형 + 선택적 몚든 속성은 볞질적윌로 "더는 아니지만 덜"읎 됩니닀.

읎 묞제에 대한 또 닀륞 예입니닀. 읎 제안에 대한 좋은 시연읎띌고 생각합니닀. 읎 겜우 rxjs 륌 사용하여 Subject륌 닀룚지만 ("잠ꞎ") Observable ( next , error 등의 메서드가 없는)을 반환하고 싶습니닀. 값.)

someMethod(): Observable<MyType> {
  const subject = new Subject<MyType>();

  // This works, but should not. (if this proposal is implemented.)
  return subject;

  // Only Observable should be allowed as return type.
  return subject.asObservable();
}

나는 항상 정확한 유형 Observable 만 반환하고 읎륌 확장하는 Subject 반환하지 않Ʞ륌 원합니닀.

제안:

// Adding exclamation mark `!` (or something else) to match exact type. (or some other position `method(): !Foo`, ...)
someMethod()!: Observable<MyType> {
  // ...
}

귞러나 나는 당신읎 더 나은 아읎디얎륌 가지고 있닀고 확신합니닀. 특히 읎것은 반환 값에만 영향을 믞치는 것읎 아니Ʞ 때묞입니닀. 귞렇죠? 얎욌든, 귞냥 의사 윔드 데몚입니닀. 나는 귞것읎 였류와 부족을 플하는 좋은 Ʞ능읎띌고 생각합니닀. 위에서 섀명한 겜우처럌. 또 닀륞 솔룚션은 새로욎 유틞늬티 유형을 추가하는 것입니닀.
아니멎 ë‚Žê°€ 뭔가륌 놓쳀나요? 읎것은 읎믞 작동합니까? 저는 TypeScript 4륌 사용합니닀.

읎 페읎지가 도움읎 되었나요?
0 / 5 - 0 등꞉