简体   繁体   中英

Most efficient way to constrain parameter type based on another parameter

I have a list of car brands, I have a car factory that takes a car and an options object that differ depending on the brand.

type CarBrand = 'mazda' | 'toyota' | 'hyundai';

export function CarFactory(car: 'mazda', options: { a: string; b: string }): object;
export function CarFactory(car: 'toyota', options: { b: string; c: string; d: string }): object;
export function CarFactory(car: 'hyundai', options: { e: string; f: string; g: number }): object;
export function CarFactory(car: CarBrand, options: any): object {
  return options;
}

This works for me at the moment, but if I have more car brands in the future it would be rather laborious adding new type signatures to overload the function. Is there a more efficient way of doing this?

I'd be inclined to make an interface representing the mapping from brand name to options, and then make your CarFactory function generic . Like this:

interface CarBrandOptions {
    mazda: { a: string; b: string };
    toyota: { b: string; c: string; d: string };
    hyundai: { e: string; f: string; g: number };
}

type CarBrand = keyof CarBrandOptions;

function CarFactory<K extends CarBrand>(car: K, options: CarBrandOptions[K]): object {
    return options;
}

This will act the same way that your current code does, I think:

CarFactory("mazda", { a: "", b: "" }); // okay

CarFactory("toyota", { a: "", b: "" }); // error! 
// Argument of type '{ a: string; b: string; }' 
// is not assignable to parameter of type '{ b: string; c: string; d: string; }'.

CarFactory("toyota", { b: "", c: "", d: "" }); //okay

but will make it easier to add more car brands by adding properties to or merging properties into the CarBrandOptions interface. Okay, hope that helps; good luck!

Link to code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM