Skip to content

TS2345 Generic parameter type, contextually inferred as a union by return at call site, will not accept all properties on object literalΒ #43044

Closed
@6XGate

Description

@6XGate

Bug Report

πŸ”Ž Search Terms

  • TS2345
  • Object literal may only specify known properties
  • several other combination I cannot recall

πŸ•— Version & Regression Information

  • This changed between sometime between versions 3.3.3 and 3.5.1

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type GetGroupKeywordsSelector = {
  profileId: string;
  groupId: string;
  metricsRange: [number, number];
};

type GetOutlierKeywordsSelector = {
  profileId: string;
  productId?: string;
  metricsRange: [number, number];
};

type MaybeGetGroupKeywordsSelector = GetGroupKeywordsSelector & { outliers?: false };
type MaybeGetOutlierKeywordsSelector = GetOutlierKeywordsSelector & { outliers: true };

type GetKeywordsSelector = MaybeGetGroupKeywordsSelector|MaybeGetOutlierKeywordsSelector;

function getKeywords(_selector: GetKeywordsSelector) {
  // Queries keywords
}

function ensureProfileId<T extends { profileId: string }>(selector: Omit<T, "profileId">): T {
  return { ...selector, profileId: "2" } as T;
}

// Compiles fine
getKeywords({
  productId: "23",
  profileId: "2",
  outliers: true,
  metricsRange: [Date.now()-500000, Date.now()]
});

// Failes with TS2345 on the productId property.
getKeywords(ensureProfileId({
  productId: "23",
  outliers: true,
  metricsRange: [Date.now()-500000, Date.now()]
}));

πŸ™ Actual behavior

The code raises a TS2345 from the compiler when attempting to use any property of a union that is not common to all types of the union. This only occurs when passing an object literal to a generic function which has inferred its generic type from contextual typing of the return type.

In this case; the language service does indicate that it has properly determined the correct type, but will not accept any uncommon property belong to only one type of the union.

πŸ™‚ Expected behavior

In less complex contexts; this would work, and seems as though it should work here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions