Skip to content

Type 'null' is not assignable to type 'T extends T ? null : Omit<T, keyof T>' #60076

Not planned
@jacobamills

Description

@jacobamills

πŸ”Ž Search Terms

"conditional type equality", "transitive generic type equality"

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.7.0-dev.20240926#code/C4TwDgpgBAKhC2YA2BDYEA8MB8UC8UAFGCgE4rwDOAXLAJT64BuA9gJYAmA3AFA9sA7dKQBmKAMbQAQoI6CA5gAUyFSlADePKFHgRKlFPIi1KwUgt4BfPoOFjJUAEoQBHCOYFKVVDVqhgPYABZPQMjWjhEVHQMAQBXJCRsKz5xFgFTKAAjWQVI5DRjWAQCmJlXBWVyKlw8P2JvGihyuU8q1QY8XDSMliQIADokFnkG6soB3X1DCDpeHh7M0hc3D3l86KKNwoxnV3dKxtr6knHaPdXD8c7cU9UBgNsQ6aNCeMS5vhE4gXFgNnS2VkWAANFBFFAIAAPdCuNRVf4oJBYbDYQjACIlTYosFgWiKBiabSLYDZFg-DjbdD4Ig3DSWXjaZbAOKkARkilU6AoNQ-ADWAhYAHd2TzilEdhDobCOGoYFAAPxQd5IKC0ADy8DYwFBUD5EBALBE4NRKR431+-0By32pBR6MxEpiOFxETotFYnF82mAxE+1nNPz+APZNtWAHEXAdxEikCB7RjxaVMC7-G7vVASRzXFyaTlXOjcZ8mSt3IQwwdPFywepHkJnmEillyTmsYVLP6vkGraHS6QAMqQcRsERsGOJECEQl+LPNzlt6kEfMcQjLvILiA1qaN2gAchELBYu47jKgFdI5b766dm40deCoRmtDnrZvJ54AfPkYE0djk7XVYbluj7hFA+6HsenznoOEDDqO45xlOXBAA

πŸ’» Code

type Template<T> = (params: T) => void;

interface BindingParams {
  message: string;
}

interface RenderingParams {
  printMessage: Template<null>;
}

const bindingTemplate: Template<BindingParams> =
  (params: BindingParams) => console.log(params.message);

const renderingTemplate: Template<RenderingParams> =
  (params: RenderingParams) => params.printMessage(null);

function bind<T, P extends Partial<T>>(t: Template<T>, p: P) {
  const boundTemplate = () => {};
  return boundTemplate as unknown as Template<P extends T ? null : Omit<T, keyof P>>;
}

function render<T>(t: Template<T>, p: T): void {
  t(p);
}

function renderGenerically<T>(t: Template<T>, p: T) {
  const boundTemplate = bind(t, p);
  render(renderingTemplate, {printMessage: boundTemplate});
}

function renderSpecifically() {
  const boundTemplate = bind(bindingTemplate, {message: 'foo'});
  render(renderingTemplate, {printMessage: boundTemplate});
}

renderGenerically(bindingTemplate, {message: 'foo'});
renderSpecifically();

πŸ™ Actual behavior

Got the error:

Type 'null' is not assignable to type 'T extends T ? null : Omit<T, keyof T>'

Seems like the TS compiler should be able to figure out that T extends T is true?

πŸ™‚ Expected behavior

No error. Since T extends T should be true, null should be assignable to null

Additional information about the issue

This may be related to #27024 (comment) (?)

Activity

jcalz

jcalz commented on Sep 26, 2024

@jcalz
Contributor

Working as intended as per #46429; the check needed for this to work does very bad things to compiler performance.

P extends T ? null : Omit<T, keyof P> is a distributive conditional type, so TS doesn't try to do it. If you can make it non-distributive like [P] extends [T] ? null : Omit<T, keyof P> then it should start working for you. If not, just use a type assertion and move on.

added
Design LimitationConstraints of the existing architecture prevent this from being fixed
on Sep 26, 2024
typescript-bot

typescript-bot commented on Sep 29, 2024

@typescript-bot
Collaborator

This issue has been marked as "Design Limitation" 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jcalz@RyanCavanaugh@jacobamills@typescript-bot

        Issue actions

          Type 'null' is not assignable to type 'T extends T ? null : Omit<T, keyof T>' Β· Issue #60076 Β· microsoft/TypeScript