-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Open
Description
π Search Terms
"this is" "type predicate" "intersection" "union"
π Version & Regression Information
- This changed between versions 4.7.4 and 4.8.4
β― Playground Link
π» Code
// === SETUP
type Update = { update_id: number };
class Context {
constructor(public update: Update) {}
check(): this is Checked {
return true;
}
}
type Checked = { update: { REMOVE_THIS_TO_FIX?: never } };
// === TYPE MAGIC
type FilterContext<C extends Context, Q extends string> = PerformQuery<
C,
RunQuery<Q>
>;
// apply a query result by intersecting it with Update, and then injecting into C
type PerformQuery<C extends Context, U extends object> = U extends unknown
? C & { update: Update & U }
: never;
type RunQuery<Q extends string> = Combine<AssertKey<Q>, Q>;
type AssertKey<Q extends string> = Q extends unknown
? Record<Q, NonNullable<unknown>>
: never;
// define additional fields on U with value `undefined`
type Combine<U, K extends string> = U extends unknown
? U & Partial<Record<Exclude<K, keyof U>, undefined>>
: never;
// === HOW IT BREAKS
declare const ctx: FilterContext<
FilterContext<Context, "one" | "two">,
"two"
>;
const works = ctx.update.update_id;
type Works = (typeof ctx & Checked)["update"]["update_id"];
if (ctx.check()) {
const breaks = ctx.update.update_id;
}π Actual behavior
In the line where the variable breaks is defined, ctx.update is never
π Expected behavior
The variable breaks can be defined and it has type number
Additional information about the issue
If you change a seemingly unrelated piece in the code, the error goes away!
// Replace
type Checked = { update: { REMOVE_THIS_TO_FIX?: never } };
// by
type Checked = { update: { } };and then everything works as expected.
darvesh
Metadata
Metadata
Assignees
Labels
No labels