question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

When possible, remove fully-excluded constituents of a union-constrained type parameter from the false arm of a conditional type

See original GitHub issue

Bug Report

🔎 Search Terms

narrow type, mapped type, union

🕗 Version & Regression Information

Tested on latest version 4.6.2

⏯ Playground Link

Playground link with relevant code

💻 Code

import { ComponentType } from "react"

export type ElementConstraint = keyof JSX.IntrinsicElements | ComponentType<any>

export type ElementProps<Element extends ElementConstraint> =
	Element extends ComponentType<infer P>
	? P : JSX.IntrinsicElements[Element]
//                ^?
// WRONG: Here JSX.IntrinsicElements[Element] complains that Element cannot be used to index JSX.IntrinsicElements eventhoug we know it must be keyof JSX.IntrinsicElements...

🙁 Actual behavior

TS doesn’t narrow the type and thus throws an error.

🙂 Expected behavior

When generic is constrained by a union type (e.g. A | B) then the conditional type should narrow the type when checking against one of those types from the union. T extends A ? <here we know it must be A type> : <here we know it must be B type>

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:2
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
Elias-Grafcommented, Oct 4, 2022

Since this is tagged as “awaiting more feedback”, I’ll quickly leave some (what I believe are simpler, - or at least easier to understand) examples here, from my issue, which was marked as duplicate.

Adding “special cases” to a ObjVal type (generic over Key):

interface Obj {
  foo1: number;
  foo2?: number;
  bar1: string;
  bar2?: string;
}

type SpecialCase = { id: number };
type ObjKey = keyof Obj | "specialCase";

// Trying to handle the "special case" key:
type ObjVal<Key extends ObjKey> = Key extends "specialCase" ? SpecialCase : Obj[Key];
  // Does not work... Error: Type 'Key' cannot be used to index type 'Obj'.(2536)

Playground

Trying to extract the value type, of a particular key, that is only present in one part of the union:

type A = {x: string;};
type B = {y: string;};
type Both = A | B;
// Type '"y"' cannot be used to index type 'T'.(2536)
type X1<T extends Both> = T extends A ? T["x"] : T["y"];
// Type '"x"' cannot be used to index type 'T'.(2536)
type X2<T extends Both> = T extends B ? T["y"] : T["x"];

Playground


I would like it if TypeScript, where it is “sound”, at least tried to evaluate the false branch of the conditional type. I don’t think what I’m trying to do here is that unreasonable 😃.

1reaction
alesmenzelcommented, Apr 20, 2022

Thanks for the suggestion, but the simpler version has 2 issues

  • T is not used in the first statement
  • IsB<T> shows a squiggly, because TS doesn’t narrow the generic T to type “B” so it complains that you cannot use T in isB<T> because the T must be of type “B”, which it is, but TS doesn’t know it yet. (playground)
Read more comments on GitHub >

github_iconTop Results From Across the Web

typescript - How to do runtime type checking conditionally for ...
Conditional types that depend on generic type parameters are hard to work with. The compiler does perform any control flow analysis on ...
Read more >
ARM Templates, conditional deployments in Azure
There is no change when using Incremental mode but nn complete mode, when a conditional resource is re-deployed and the condition is false,...
Read more >
Documentation - TypeScript 2.8
A conditional type selects one of two possible types based on a condition ... type is a naked type parameter are called distributive...
Read more >
TypeScript: Conditional Types Explained - Ross Bulat - Medium
Conditionals are often coupled with generic types (otherwise termed type parameters) to test whether such parameter meets a certain ...
Read more >
Method code too large! - Jeecgboot/Jeecg-Boot - IssueHint
When possible, remove fully-excluded constituents of a union-constrained type parameter from the false arm of a conditional type, 2, 2022-04-14, 2022-09-22.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found