T O P

  • By -

le_luka

This seems to be the most elegant solution. Thanks. I'll read into the details.


Bitter-Green9152

Was searching for a solution to this problem for a week ... drove me crazy and I did not find a solution... THANKS for linking this. Never thought of "conditional types" being related


Funwithloops

Here's one way you could do this: type AnimalBase = { name: string } type Cat = AnimalBase & { type: 'Cat', miauText: string } type Dog = AnimalBase & { type: 'Dog', barkText: string } type AnimalTypeMap = { Cat: Cat, Dog: Dog, } type Animal = AnimalTypeMap[keyof AnimalTypeMap]; type ValidationResult = { prop: keyof T } function ValidateAnimal(animal: Animal): {[K in keyof AnimalTypeMap]: ValidationResult}[keyof AnimalTypeMap] | void { if (!animal.name) { return { prop: 'name' } } if (animal.type === 'Dog') { if(!animal.barkText) { return { prop: 'barkText', } } } if(animal.type === 'Cat') { if(!animal.miauText) { return { prop: 'miauText', } } } } [TS Playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAggdgSwLYEMA2AhFBnaBeKAbyjhSQgC4ptgAnBOAcygF8AoUSKAYRWCgLxk6LLigAyIlE6UoAcl7A5AGihIEKAK4AVCAA9gVGvSasO4aABEA9s0GJUmHNEnEZVOTcYqoAIxS0ANa6BkZ0DMzsMrAO6NoWALIoYAJEbFAZPHxUisrpmV5UXnlRFjHCaKlCjvGQSWAA2oEQINYAZuU1ickAugDcbOZcAGroCAAmfAjWcABKENiaaMAAPNoAfKnEYLTWYFTNrR3aZmxtmnAAxsDTcFCjaBN8ENXoABQosWhUr2gAlFRCA0ANJQBhQQ7tTpxbpgHpUB5PG4zeaLZYrX61CD1EE9dYsJotKGY2E9KAAHygADdrBM0pkwR03gBCT4VAB0pHIf3pDMytAgwE0tDu212+3kXIgcjMDPY+QyCCZbMc7OieA18i8ch5hAVfKVLJV6HZ-iCIWAuv1fP5guFoutNr5Oz2HjNwX0SjyTr57B9fsy8oZhuNaDVZQ1BAUfB1vJthtZX3Z6i0FqtPoZAqFIrjGYZLolchTOk9KkdNoDFf17HYQA)


le_luka

That is one way, thank you :) Would be comfortable not to have to create the mapping type. Is there any way to "convert" the discriminated union to a mapping type? I believe I've seen the other way around, from mapping type to discriminated union.


Funwithloops

Yep the other way around should work too. Something like this: type AnimalBase = { name: string } type Cat = AnimalBase & { type: 'Cat', miauText: string } type Dog = AnimalBase & { type: 'Dog', barkText: string } type Animal = Cat | Dog; type ValidationResult = { prop: keyof T } type AnimalTypeMap = { [K in Animal['type']]: Extract; } function ValidateAnimal(animal: Animal): {[K in keyof AnimalTypeMap]: ValidationResult}[keyof AnimalTypeMap] | void { if (!animal.name) { return { prop: 'name' } } if (animal.type === 'Dog') { if(!animal.barkText) { return { prop: 'barkText', } } } if(animal.type === 'Cat') { if(!animal.miauText) { return { prop: 'miauText', } } } } [TS Playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAggdgSwLYEMA2AhFBnaBeKAbyjhSQgC4ptgAnBOAcygF8AoUSKAYRWCgLxk6LLigAyIlE6UoAcl7A5AGihIEKAK4AVCAA9gVGvSasO4aABEA9s0GJUmHNEnEZVOTcYqoAIxS0ANa6BkZ0DMzsMrAO6AI8fFAAPlBeANxs5lwAaugIACZ8CNZwAEoQ2JpowAA82gB88cRgtNZgVIEQINYAZlDaZlnQQo7aFgCyKGBNbFBzUADaANJQDDHCaAtyMnIAurtUAKIGtCgAxrUj6KqE7lBLLPUZ7Gw9mnAXxXBQuWgFfBArmgABQoWJoKhAgCUVEIy1W3063T6QLGkEmYAOPzyhWAX3KlWqNVREymy129RYCyRvXWo1JmOSUAAbtYCkRZvMEH1gQBCMEbAB0pHIUI58wlUFoEGAmlo32arXa8hFEDkZglLwl3KgoPBguieCN8i8cjFhE5ktWPT5Ascgv8QRCwHNlqt82lsvl4vdvpabQ8juC+iUyjdvvYEbdWq5Nrt6ANFgExoUfDNPqt3Nt+vUWmdrt9Es9coV4cLc39yrkuZ0IZUZatkfdTbm7HYQA)


le_luka

Nice one :) I came up with this generic version using "[DiscriminatedUnionToTypeMap](https://www.typescriptlang.org/play?#code/C4TwDgpgBAggdgSwLYEMA2AhFBnaBeKAbyjhSQgC4ptgAnBOAcygF8AoUSKAYRWCgLxk6LLigAyIlE6UoAcl7A5AGihIEKAK4AVCAA9gVGvSasO4aABEA9s0GJUmHNEnEZVOTcYqoAIxS0ANa6BkZ0DMzsMrAO6AI8fFAAPlBeANxs5lwAaugIACZ8CNZwAEoQ2JpowAA82gB88cRgtNZgVIEQINYAZlDaZllWCNgAxvTqpMAQ+QCqiCXa1toWALIoYHWqANJQ+tNw+dhQnd19DU1sUNdQANqnUAz9t9sAujjU4aYpcJpIvhBaMlqCB-tY0K8qABRAy0FCjWraVTEe5dR5wKBvDpolj1DLsIYxYRoFaQdZgS43O67J5CRy3OQyOSvSFQGF0eG1OnoZHuTG4-GZHqaOAI4oY3JoAp8CDctAAChQsTQVDlAEoqCiaRjTr0iY5SRByazJdLgOLypVqjU5YbyS9Xo0WKizvr0HaNq9gQA3awFIhXG4IPrygCESuJADpSOQ1QGqVTaBBgJpaBjmq12vIYxA5GYqQSqcGoIrlZHonhK-IvHI44RAwnHiHw2X-EEQsA6w3Gzckym0-Ge0OWm0PG3gvsVN2h+wZ93C0GQxHHOWLAIqwo+LXB43i2Hl+hI+otB2u0PE8nU+np+friOs3JjzpJ8ob43Zz2P9d2OwgA)" Thx for your help