简体   繁体   中英

TypeScript: Return type has all keys specified as parameter

I would like to type a function in a way, that the return type will be an object, that contains exactly the keys specified in an array as a parameter. Also these keys should all be of a specific enum type. I've already tried a couple of things, but can't get it working. Maybe someone knows if it's possible at all and how?

enum Status {
  TIME = 'time',
  LOCATION = 'location'
}

function getStatus(statusToGet: Status[]) {
  // This function will always return an object containing all passed in
  // status as a key and boolean as a value, e.g.
  return statusToGet.reduce((prev, stat) => {
    prev[stat] = true; // or false
    return prev;
  }, {});
}

getStatus([]) // -> {}
getStatus([Status.TIME]) // -> { time: true }
getStatus([Status.TIME, Status.LOCATION]) // -> { time: true, location: false }

Is it possible to type the getStatus function correctly, so that TS knows which keys are in the return type?

You can use mapped types to map an array of string literal types to an object :

enum Status {
    TIME = 'time',
    LOCATION = 'location'
}

function getStatus<T extends Status>(statusToGet: T[]): { [P in T]: boolean } {
    return null as any;
}

getStatus([]) // -> {}
getStatus([Status.TIME]) // -> { time: true }
getStatus([Status.TIME, Status.LOCATION]) // -> { time: true, location: false }

Note The above code returns { [s:string] :any} for an empty array if strict null checks are not enabled. This happens because T will be inferred to any . To get around this we can use a conditional type to test if T is any and return {} explicitly (10x to @jcalz for the any test from this answer ). This does mean any array of any will produce {} but since we expect an array of enum values not an array of any this migh not be too much of a problem, might actually be a feature.

function getStatus<T extends Status>(statusToGet: T[]): true extends false & T?  {} : { [P in T]: boolean } {
     return null as any;
}

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