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

Generic type inference is lost when partially specified #39008

Closed
davidkpiano opened this issue Jun 10, 2020 · 2 comments
Closed

Generic type inference is lost when partially specified #39008

davidkpiano opened this issue Jun 10, 2020 · 2 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@davidkpiano
Copy link

davidkpiano commented Jun 10, 2020

TypeScript Version: 3.7+ (including 4.0 Nightly)

Search Terms:

generic inference object restriction constraint

Code

// Restrict `initial` to be `keyof TStates`
interface Config2<T, TStates extends { [key: string]: any } = any> {
    context: T;
    states: TStates;
    initial: keyof TStates;
}

// Can't partially specify <T, TStates>, so default to any
function config2<T, TStates = any>(config: Config2<T, TStates>) { }

config2({
    context: { count: 0 },
    states: { foo: {}, bar: {} },
    initial: 'foo' // ✅ Properly checked!
    // initial: 'anything' // will not compile as expected
});

config2<{ count: number }>({
    context: { count: 0 },
    states: { foo: {}, bar: {} },
    initial: 'anything' // ❌ improperly allowed
});

Expected behavior:

In the above code, TStates should still be inferred to { foo: {}, bar: {} } so that .initial can be restricted to keyof TStates, which is 'foo' or 'bar' only. This works when no generic types are specified.

The goal is to express restriction/constraint within an object, which the above example shows: .initial should be restricted to a key of .states.

Actual behavior:

When 1 (or more) generic types are specified, the rest are "forced" to their defaults (any in this case), so inference is lost. In the above code, initial: 'anything' should cause a type error.

Playground Link: https://www.typescriptlang.org/play/?ts=4.0.0-dev.20200609&ssl=39&ssc=4&pln=18&pc=1#code/PTAEDkHtQJwUwM4BcYEsDGTWQHYChUck4YAzAQ3TlAGFdTUBzARgB4AVAPlAG89QBodLmIAPJAC5Q7ANz9BycsQRS+g9aADaAazgBPKcjQ5GAXSnkceueoC+NwYVRZyAG0MpCjObbx5SAK44mNg4QvRMbFwAFMI4DIxSdPGRHJwAlLygvnhxCczRaoJxYpJZwkFlAAzZADTyAorKqqCkkJCqtrWgAEbkMJ11DaBOLu6gAOSWekgAFl4ToCCgjJBuhrOQAa4AJqA4kEi91G6ukADucDt4tulyeMsASoiemKAABqOobu+gSNA9ajvXR6SCkaQAZSQSkQ7wIRBIFCotAijAATBxuuwoTCEKA4OI4DgdnieFoQR5jGYLFZsqAALygabcIoCEoEsqyYZNRBSbHQ5QOARfdagEFgyECxA+PzLGiWCZHAAO-TGrj0oAQSrg6FQpA1mMluM43QQ0B2cAo2yO-yZVn8QRCuHCKXRhv5uIZdr0nFiqKSqIx7CxOOUGSyOTyTDRhWG7PELQqRCkNS63KlKiybQ6vC6vX6gzT6hF4wm2cWy0AoOSgAAKMEg2pg6qEsx1uh2AEJhssS1IplY5gslmBzqhXK59odwgBbJVjk54gnazBXG53PxRt1kpNlHABaeAmDZX2sl2lRNbZOgVP1dQ8zNk7Odbp9Aa5obFnDOb6l6aDkwVmAgAy5JqmzbHsBxHICTLjhcq63DIQA

Related Issues: No, but here's a related link: https://stackoverflow.com/questions/54664214/typescript-relate-to-own-property-in-type

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 10, 2020
@RyanCavanaugh
Copy link
Member

When any type arguments are specified, the remaining arguments are set to their defaults rather than going through inference. IMHO this was probably a mistake, but it was written that way on purpose and would be too large of a breaking change to modify at this point. See #26349 and related issues

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants