😄), туплю.
Помогите выбраться, пожалуйста.
Как сделать так, чтобы тайпскрипт принимал только тип, четко соответствующий ОДНОМУ из значений в union типе, а не всем подряд?
Подробнее про задачу:
1) Есть продукты разных типов ProductType, каждый тип продукта имеет свой тип опций (ShirtOptions, например). Опции и продукт мапятся отдельным типом ProductOptionsMap
2) Есть корзины разных типов CartType: по одному для каждого типа продукта + (!!!) тип "all" (ProductType | "all") . В корзину можно складывать только продукты заданного типа (мапится отдельным типом CartProductMap)
3) Есть функция добавления в корзину, которая должна быть строго типизирована и ругаться, если мы в корзину "shirts" будем добавлять товар "pants". Ну или если мы в корзину "all" добавляем продукт, который имеет опции, несоответствующие ни одному из *Options типу
type CartProduct<T extends ProductType> = {
productType: T
uuid: string
options: ProductOptionsMap[T] // I want it to be exact mapped options to productType, but in case with "all" it is union of all ProductType's options
}
type Cart<T extends CartType> = CartProduct<CartProductMap[T]>[]
function addToCart<T extends CartType>(cart: T, product: CartProduct<CartProductMap[T]>) {
// add to cart of type T product with type that available for this cart
}
addToCart("shirt", {productType: "shirt", uuid: "123", options: {color: "red", width: 10}}) // OK
addToCart("pants", {productType: "pants", uuid: "123", options: {length: 20}}) // OK
addToCart("pants", {productType: "pants", uuid: "123", options: {color: "red"}}) // TS error here. Thats rigth.
addToCart("all", {productType: "pants", uuid: "123", options: {length: 20, color: "red", width: 10}}) // WHY no TS Error here???
Плейграунд:
https://www.typescriptlang.org/play?#code/C4TwDgpgBACgTgewCYFcDGwAq5oF4oBEAzgBYCWcwBUAPoWAIYB2wRBAUO6JFAMIOVsPfPGTosOWoQYAbGdQD0CqAibRu0AGYI4UCADcIcEFDCJUGKBqgBqKGgHAo23QEEAMu6s4iKzafNxIk5rAGVySgB5MGAyVV98AG92KHsEGR0ALigiYDgyJgBzFKgAdzIkYBJsphQAWwAjIyh2AF8QyRhmVmjY+KgkkpkIIqqa+qa4No6eUQtgXrimIgBZBjABqGTU4giqbPCKBZil4J3GFjZsrsvF+OmuSX5KOfE1jcHUgG0AaSgC2CBDBCCAAXWyfyUzh0hFIR2oZF8u3hABpoboCBdWAjWPRumw2lAAGRbEoEWTya5AiSQB7WZ7AV4YAA8mD0AA9gCMkL4mTSIAA+TbbAJiYE4bKYEooFAVbK5fJFEoIE7xKli459ZbvL6YUFQKEASTK3X+TmACCgTQ5DEsdXWkCQKlVyyslrMGpBaIaKCcAIcRGg5Sq0jkOP+vhQTCWfigFMBnpwAHJfCqtcF2o8eAzWRyuUweXxHCChfgGXzmeXqTq9QKvqDOJooxgYwwkEhMAgc2yIJzub4GSWABQOSiStEe+bZKsayuOPk10ECgCUpNSULbTot9kcsesbMn4jKZBD1iqDCcDH0DDIMgYDWG6Ks5F8o+AD03nYZQ+RlAIaMSQ9xUgbJfyoNEZTlQgAEYACYAGZ-2ddNskSNB0iyQg4AgJAkPKSpqigaCAAZWlaZd2E-LtHB-LE2AAoD+VAuikMgpBQLgxC0TTU5UOGUZCNg0jyMo9svxozF8SQwDqRBZipIg2V2JghCkJ4tUtnQjI4FA7DcLI1coUwUI9DgRBdBIIwIAAOigTASAvXx8kKKprNEjtqMoH8KWkxi5LxS5WKUjjVO4l0iD4kYXME4i0S0zCCD0vCKjGIjhMM5QAHUAAkAE0oCYS1jKgABRMyYUs7CAH4as4TggA
Задача упростилась до: как сделать так, чтобы TS ругался здесь, что объект не соответствует строго одному из типов? type ShirtOptions = { color: string width: number } type PantsOptions = { length: number } type allOptions = PantsOptions | ShirtOptions const expectTSErrorHere: allOptions = { // <<<< EXPECT ERROR HERE, because there is no exact such type color: "red", length: 20 }
добавить в тип дискриминатор type ShirtOptions = { type: 'shirt' color: string width: number } type PantsOptions = { type: 'pants' length: number }
Вау, спасибо большое! Побежал читать про дискриминаторы❤️
Обсуждают сегодня