Search code examples
javascriptreactjsangulartypescriptreact-redux

TypeScript: an interface property dependent on another


is it possible to type an interface property dependent on another?

For example I have:

const object = {
  foo: 'hello',
  bar: { hello: '123', },
}

And I want to make sure that the key of bar must be the value of foo.

interface ObjectType = {
  foo: string;
  bar: { hello: string; } // instead of hardcoding have something like this? --> payload: { ValueOfFoo: string; }
}

Thanks! :)


Solution

  • You need a generic to capture the type of a specific string

    interface ObjectType<K extends string> {
        foo: K;
        bar: { [P in K]: string };
    }
    

    Then you can write

    const object: ObjectType<'hello'> = {
        foo: 'hello',
        bar: { hello: '123', },
    };
    

    Or, if you have a function that takes such an object you can use the interface to enforce the rule with full type inference

    function useObject<K extends string>(o: ObjectType<K>) { }
    
    useObject({
        foo: 'hello', 
        bar: { hello: '113' } // works
    });
    
    useObject({
        foo: 'hello', 
        bar: { world: '113' }
    //         ^^^^^−−−−−−−−−−−− error, `world` should be `hello`
    });
    

    Playground link