Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Property Type inference problem when picking property with index key type #39945

Closed
dumasss163 opened this issue Aug 7, 2020 · 1 comment
Closed

Comments

@dumasss163
Copy link

dumasss163 commented Aug 7, 2020

TypeScript Version: 3.9.5

Search Terms:

  • [K in keyof T]: T[K] extends V | undefined | null
  • type T[keyof T] does not
  • infer property type

Code

given the following 2 structures, they look like the same, i.e. a parent-child relationship

interface Category {
  children?: this[],
  parent?: this
}

interface Node {
  items?: this[],
  parent?: this
}

I want to access them the same way, by giving the relative property names, e.g. 'children'/'items' for child relation and 'parent' for parent relation, like this:

let category: Category = {};
// access children and parent of category
handle(category, 'children', 'parent'); //!! <- inference problem here

let node: Node = {};
// access items and parent of node
handle(node, 'items', 'parent'); //!! <- inference problem here

here is how I define the handle method with some helpers

type Nullable<T> = T | undefined | null;

type PickKey<T, V> = keyof {
  [K in keyof T]: T[K] extends Nullable<V> ? K : never
};

export function handle<
  T extends Record<PickKey<T, T[]>, Nullable<T[]>
    & Record<PickKey<T, T>, Nullable<T>>
  >
>(
  tree: T,
  childrenKey: PickKey<T, T[]>,
  parentKey: PickKey<T, T>,
) {
  let parent = tree[parentKey];
  if (parent) {
    let siblings = parent[childrenKey];
  }
  let children = tree[childrenKey];
  if (children) {
    for (let ii = 0; ii < children.length; ii++) {
      const child = children[ii];
    }
  }
}

Expected behavior:

It should compile

Actual behavior:

Argument of type 'Category' is not assignable to parameter of type 'Record<"children" | "parent", Category[] & Record<"children" | "parent", Nullable<Category>>>'.
  Types of property 'children' are incompatible.
    Type 'Category[] | undefined' is not assignable to type 'Category[] & Record<"children" | "parent", Nullable<Category>>'.
      Type 'undefined' is not assignable to type 'Category[] & Record<"children" | "parent", Nullable<Category>>'.
        Type 'undefined' is not assignable to type 'Category[]'.ts(2345)

Playground Link:

Related Issues:

it is related, but not really the same
#38646

@jack-williams
Copy link
Collaborator

Did you try any of the solutions in #12290?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants