Skip to content

Unexpected "does not satisfy the constraint" #14759

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

Closed
jamesknelson opened this issue Mar 21, 2017 · 1 comment
Closed

Unexpected "does not satisfy the constraint" #14759

jamesknelson opened this issue Mar 21, 2017 · 1 comment
Labels
Duplicate An existing issue was already created

Comments

@jamesknelson
Copy link

TypeScript Version: 2.2.1

Code

type Group = {
    [key: string]: string;
}

class Foo<G extends Group> {
    attributes: G;
}

declare function createResource<G extends Group>(x: G): Foo<{ [K in keyof G]: string }>;

Expected behavior:

This should compile, I think. { [K in keyof G]: string } does satisfy { [key: string]: string }.

Actual behavior:

The compiler outputs the following:

type-error-demo.ts(9,61): error TS2344: Type '{ [K in keyof G]: string; }' does not satisfy the constraint 'Group'.

Use case:

This is a larger example which is closer to the original use case. The idea is to add "keys" to the passed in object's values based on the passed in object's keys.

type AttributeOptions<P> = {
    default: P;
}
type AttributeOptionsSet = {
    [key: string]: AttributeOptions<any>;
}

type Attribute<P> = {
    key: string;
    default: P;
}
type AttributeSet = {
    [key: string]: Attribute<any>;
}

class Resource<As extends AttributeSet> {
    attributes: As;
}

declare function createResource<AOs extends AttributeOptionsSet>(x: AOs): Resource<{ [Key in keyof AOs]: Attribute<AOs[Key]["default"]> }>;

A hacky way to make this compile involves adding a generic to AttributeSet that contains its keys, and letting typescript infer them:

type AttributeOptions<P> = {
    default: P;
}
type AttributeOptionsSet = {
    [key: string]: AttributeOptions<any>;
}

type Attribute<P, Key extends string> = {
    key: Key;
    default: P;
}
type AttributeSet<Keys extends string> = {
    [Key in Keys]: Attribute<any, Key>;
}

class Resource<As extends AttributeSet<keyof As>> {
    attributes: As;
}

// This actually compiles
declare function createResource<AOs extends AttributeOptionsSet>(x: AOs): Resource<{ [Key in keyof AOs]: Attribute<AOs[Key]["default"], Key> }>;

The problem with this is that it causes tsc to fail further through the application code -- see my comment in #14723

@RyanCavanaugh
Copy link
Member

Same as #14548

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants