Home > OS >  How to type a T object with at least one property like K?
How to type a T object with at least one property like K?

Time:02-01

I have a function like this:

function flatten(tree, property) {
    // ... implementation
    return tree[property];s
}

I would like to restrict types of arguments with TypeScript so that it would be generic and fit the type like this:

type Tree = {
    subTree: Tree;
    name: string;
}

e.g.

function flatten(tree: Tree, property: 'subTree'): Tree {
    // ... implementation
    return tree[property];
}

But with generics:

function flatten<T, K>(tree: T, property: K): T {
    return tree[property];
}

The above of course doesn't work

I looked at this Typescript: object with at least one property of type T but it's not what I want

I would like to restrict type T so it has at least one property named K of type T

ts sandbox

CodePudding user response:

You can write recursive constraints, so you should make sure that property is of a generic type K constrained to a keylike type (the PropertyKey utility type is just an alias for string | number | symbol), and that tree is of a generic type T constrained to Record<K, T> (the Record<K, T> utility type is just an alias for a simple mapped type saying a type with properties of type T at the keys of type K):

function flatten<T extends Record<K, T>, K extends PropertyKey>(tree: T, property: K): T {
    return tree[property];
}

That compiles with no error. Let's test it on your example structure:

type Tree = {
    subTree: Tree;
    name: string;
}
declare const tree: Tree;
flatten(tree, "subTree"); // okay
flatten(tree, "name"); // error

Looks good. If you pass in "name" as the property, then tree is not a valid structure (since tree.name is not of the same type as tree), but if you pass in "subTree" then everything is fine.

Playground link to code

  • Related