mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
Allow discrimination to identical object types when discriminating contextual types (#40574)
* Merge identical object types when discriminating contextual types Co-authored-by: Orta <ortam@microsoft.com> * Allow identical discriminants when discriminating, rather than trying to unify identical union members * Fix lint Co-authored-by: Orta <ortam@microsoft.com>
This commit is contained in:
parent
ad2a07440c
commit
a91c2879ef
@ -18348,8 +18348,18 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
const match = discriminable.indexOf(/*searchElement*/ true);
|
||||
if (match === -1) {
|
||||
return defaultValue;
|
||||
}
|
||||
// make sure exactly 1 matches before returning it
|
||||
return match === -1 || discriminable.indexOf(/*searchElement*/ true, match + 1) !== -1 ? defaultValue : target.types[match];
|
||||
let nextMatch = discriminable.indexOf(/*searchElement*/ true, match + 1);
|
||||
while (nextMatch !== -1) {
|
||||
if (!isTypeIdenticalTo(target.types[match], target.types[nextMatch])) {
|
||||
return defaultValue;
|
||||
}
|
||||
nextMatch = discriminable.indexOf(/*searchElement*/ true, nextMatch + 1);
|
||||
}
|
||||
return target.types[match];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4170,7 +4170,7 @@ namespace ts {
|
||||
export const enum UnionReduction {
|
||||
None = 0,
|
||||
Literal,
|
||||
Subtype
|
||||
Subtype,
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
//// [inferenceUnionOfObjectsMappedContextualType.ts]
|
||||
type Entity = {
|
||||
someDate: Date | null;
|
||||
} & ({ id: string; } | { id: number; })
|
||||
|
||||
type RowRendererMeta<TInput extends {}> = {
|
||||
[key in keyof TInput]: { key: key; caption: string; formatter?: (value: TInput[key]) => string; };
|
||||
}
|
||||
|
||||
type RowRenderer<TInput extends {}> = RowRendererMeta<TInput>[keyof RowRendererMeta<TInput>];
|
||||
|
||||
const test: RowRenderer<Entity> = {
|
||||
key: 'someDate',
|
||||
caption: 'My Date',
|
||||
formatter: (value) => value ? value.toString() : '-' // value: any
|
||||
}
|
||||
|
||||
|
||||
//// [inferenceUnionOfObjectsMappedContextualType.js]
|
||||
"use strict";
|
||||
var test = {
|
||||
key: 'someDate',
|
||||
caption: 'My Date',
|
||||
formatter: function (value) { return value ? value.toString() : '-'; } // value: any
|
||||
};
|
||||
@ -0,0 +1,56 @@
|
||||
=== tests/cases/compiler/inferenceUnionOfObjectsMappedContextualType.ts ===
|
||||
type Entity = {
|
||||
>Entity : Symbol(Entity, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 0, 0))
|
||||
|
||||
someDate: Date | null;
|
||||
>someDate : Symbol(someDate, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 0, 15))
|
||||
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
|
||||
|
||||
} & ({ id: string; } | { id: number; })
|
||||
>id : Symbol(id, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 2, 6))
|
||||
>id : Symbol(id, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 2, 24))
|
||||
|
||||
type RowRendererMeta<TInput extends {}> = {
|
||||
>RowRendererMeta : Symbol(RowRendererMeta, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 2, 39))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 4, 21))
|
||||
|
||||
[key in keyof TInput]: { key: key; caption: string; formatter?: (value: TInput[key]) => string; };
|
||||
>key : Symbol(key, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 5))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 4, 21))
|
||||
>key : Symbol(key, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 28))
|
||||
>key : Symbol(key, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 5))
|
||||
>caption : Symbol(caption, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 38))
|
||||
>formatter : Symbol(formatter, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 55))
|
||||
>value : Symbol(value, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 69))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 4, 21))
|
||||
>key : Symbol(key, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 5, 5))
|
||||
}
|
||||
|
||||
type RowRenderer<TInput extends {}> = RowRendererMeta<TInput>[keyof RowRendererMeta<TInput>];
|
||||
>RowRenderer : Symbol(RowRenderer, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 6, 1))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 8, 17))
|
||||
>RowRendererMeta : Symbol(RowRendererMeta, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 2, 39))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 8, 17))
|
||||
>RowRendererMeta : Symbol(RowRendererMeta, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 2, 39))
|
||||
>TInput : Symbol(TInput, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 8, 17))
|
||||
|
||||
const test: RowRenderer<Entity> = {
|
||||
>test : Symbol(test, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 10, 5))
|
||||
>RowRenderer : Symbol(RowRenderer, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 6, 1))
|
||||
>Entity : Symbol(Entity, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 0, 0))
|
||||
|
||||
key: 'someDate',
|
||||
>key : Symbol(key, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 10, 35))
|
||||
|
||||
caption: 'My Date',
|
||||
>caption : Symbol(caption, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 11, 20))
|
||||
|
||||
formatter: (value) => value ? value.toString() : '-' // value: any
|
||||
>formatter : Symbol(formatter, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 12, 23))
|
||||
>value : Symbol(value, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 13, 16))
|
||||
>value : Symbol(value, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 13, 16))
|
||||
>value.toString : Symbol(Date.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>value : Symbol(value, Decl(inferenceUnionOfObjectsMappedContextualType.ts, 13, 16))
|
||||
>toString : Symbol(Date.toString, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
=== tests/cases/compiler/inferenceUnionOfObjectsMappedContextualType.ts ===
|
||||
type Entity = {
|
||||
>Entity : Entity
|
||||
|
||||
someDate: Date | null;
|
||||
>someDate : Date | null
|
||||
>null : null
|
||||
|
||||
} & ({ id: string; } | { id: number; })
|
||||
>id : string
|
||||
>id : number
|
||||
|
||||
type RowRendererMeta<TInput extends {}> = {
|
||||
>RowRendererMeta : RowRendererMeta<TInput>
|
||||
|
||||
[key in keyof TInput]: { key: key; caption: string; formatter?: (value: TInput[key]) => string; };
|
||||
>key : key
|
||||
>caption : string
|
||||
>formatter : ((value: TInput[key]) => string) | undefined
|
||||
>value : TInput[key]
|
||||
}
|
||||
|
||||
type RowRenderer<TInput extends {}> = RowRendererMeta<TInput>[keyof RowRendererMeta<TInput>];
|
||||
>RowRenderer : RowRenderer<TInput>
|
||||
|
||||
const test: RowRenderer<Entity> = {
|
||||
>test : RowRenderer<Entity>
|
||||
>{ key: 'someDate', caption: 'My Date', formatter: (value) => value ? value.toString() : '-' // value: any} : { key: "someDate"; caption: string; formatter: (value: Date | null) => string; }
|
||||
|
||||
key: 'someDate',
|
||||
>key : "someDate"
|
||||
>'someDate' : "someDate"
|
||||
|
||||
caption: 'My Date',
|
||||
>caption : string
|
||||
>'My Date' : "My Date"
|
||||
|
||||
formatter: (value) => value ? value.toString() : '-' // value: any
|
||||
>formatter : (value: Date | null) => string
|
||||
>(value) => value ? value.toString() : '-' : (value: Date | null) => string
|
||||
>value : Date | null
|
||||
>value ? value.toString() : '-' : string
|
||||
>value : Date | null
|
||||
>value.toString() : string
|
||||
>value.toString : () => string
|
||||
>value : Date
|
||||
>toString : () => string
|
||||
>'-' : "-"
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
// @strict: true
|
||||
type Entity = {
|
||||
someDate: Date | null;
|
||||
} & ({ id: string; } | { id: number; })
|
||||
|
||||
type RowRendererMeta<TInput extends {}> = {
|
||||
[key in keyof TInput]: { key: key; caption: string; formatter?: (value: TInput[key]) => string; };
|
||||
}
|
||||
|
||||
type RowRenderer<TInput extends {}> = RowRendererMeta<TInput>[keyof RowRendererMeta<TInput>];
|
||||
|
||||
const test: RowRenderer<Entity> = {
|
||||
key: 'someDate',
|
||||
caption: 'My Date',
|
||||
formatter: (value) => value ? value.toString() : '-' // value: any
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user