Skip to content

Can't index object in generic function with property name extracted with Pick from derived type #40832

@popadi

Description

@popadi

TypeScript Version: 4.1.0-beta

Search Terms:
pick, generic function, keyof

Code

interface IRecord {
  id: number,
  name: string
}

type FilterProperties<T> = Pick<
  T,
  { [K in keyof T]: T[K] extends string ? K : never }[keyof T]
>;

function extract<T>(data: T[], field: keyof FilterProperties<T>): void {
  const record: T = data[0];
  const value: string = record[field]; // see error below
}

const data: IRecord[] = [{ id: 1, name: "one" }, { id: 2, name: "two" }]

extract<IRecord>(data, "id"); // expected: error that id can't be used as a parameter since it's not a string
extract<IRecord>(data, "name") // no error, expected behaviour

Expected behavior:
I'm trying to create a function that receives an object/an array of objects of type T and a field name but the user should be able to call the function only if the type of that field in T is string. FilterProperties is just a type (union) that picks those properties from T and can be easily extended to filter any kind of properties.

Since I was able to call the function correctly on the last line (because name is a field of type string, I was expecting to be able to extract the value in the function too, but I get the error below. Everything works if you define everything explicitly (no generics).

Actual behavior:

Type 'T[{ [K in keyof T]: T[K] extends string ? K : never; }[keyof T]]' is not assignable to type 'string'.
  Type 'T[T[keyof T] extends string ? keyof T : never]' is not assignable to type 'string'.
    Type 'T[keyof T]' is not assignable to type 'string'.
      Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'string'.
        Type 'T[string]' is not assignable to type 'string'.ts(2322)

Playground Link:
https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJICUIIPZQCbIDeAsAFDLLB4BcyIArgLYBG0ANGRSHIxLQM5gooAOZkAvmTJgAngAcUAMWAAbSFAAKUbAqhhgEfgB4AKgD5kAXmQbgCANZHOyEx3JFkAbQDSlEMnsIGWwYFwBdWhMfMOQIAA9IEDx+ZEFhEBFkAH5kX1oQCAA3aGRxT0Dg0JMwsjMAbilSGHoQBH1sf3ihRDBTMwAKPDgwOEjPMLZkGAMVGgCgkORlNWgtHWh9Qz6ASlpC7CoiZxwQQWQoLFw5kytkIZHPAAYwhvcTs8K4FXo+VKFRW4XHD4TzTCCzF7IAD0UNSEBQ0G0UGQrBU2AA7hJGu8wHdhqM0JhgXhxrdPIRKHMAIyTbi8WgAIg6EAZpUmFKotAATLSeL8GWB0dhWeIaqQyF0oD0jBhLvgBvc4JMGVQGds6tDYYjcMgwAALYaU5AIOAgADkuNYyHo-AgBDgKTgyDkcClvHUqVASEoYDNKRA2FxTrSoglCSlbRlRKuCvxyrpLO2mro2FiUCRk3iCjadpREANhWA2HoUCAA

Let me know if I should update the title to be more descriptive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions