mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
relax restriction on extends type of narrowable conditional type
This commit is contained in:
parent
e0d466dcca
commit
a3e7ea503d
@ -46100,7 +46100,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// (0) The conditional type is distributive;
|
||||
// (1) The conditional type has no `infer` type parameters;
|
||||
// (2) The conditional type's check type is a narrowable type parameter (i.e. a type parameter with a union constraint);
|
||||
// (3) The extends type `A` is a type or a union of types belonging to the union constraint of the type parameter;
|
||||
// (3) The extends type `A` is a type or a union of types that are supertypes of the union constraint of the type parameter;
|
||||
// (4) `TrueBranch<T>` and `FalseBranch<T>` must be valid, recursively.
|
||||
// In particular, the false-most branch of the conditional type must be `never`.
|
||||
function isNarrowableConditionalTypeWorker(type: ConditionalType): boolean {
|
||||
@ -46129,7 +46129,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
!everyType(type.extendsType, extendsType =>
|
||||
some(
|
||||
(constraintType as UnionType).types,
|
||||
constraintType => isTypeIdenticalTo(constraintType, extendsType),
|
||||
constraintType => isTypeAssignableTo(constraintType, extendsType),
|
||||
))
|
||||
) {
|
||||
return false;
|
||||
|
||||
61
tests/baselines/reference/dependentReturnType10.symbols
Normal file
61
tests/baselines/reference/dependentReturnType10.symbols
Normal file
@ -0,0 +1,61 @@
|
||||
//// [tests/cases/compiler/dependentReturnType10.ts] ////
|
||||
|
||||
=== dependentReturnType10.ts ===
|
||||
interface Animal {
|
||||
>Animal : Symbol(Animal, Decl(dependentReturnType10.ts, 0, 0))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18))
|
||||
|
||||
species: string;
|
||||
>species : Symbol(Animal.species, Decl(dependentReturnType10.ts, 1, 17))
|
||||
}
|
||||
|
||||
interface Dog extends Animal {
|
||||
>Dog : Symbol(Dog, Decl(dependentReturnType10.ts, 3, 1))
|
||||
>Animal : Symbol(Animal, Decl(dependentReturnType10.ts, 0, 0))
|
||||
|
||||
breed: string;
|
||||
>breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30))
|
||||
}
|
||||
|
||||
type GreetRet<T> =
|
||||
>GreetRet : Symbol(GreetRet, Decl(dependentReturnType10.ts, 7, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14))
|
||||
|
||||
T extends string ? string :
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14))
|
||||
|
||||
T extends { name: string } ? { greeting: string, breed: string } :
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 9, 14))
|
||||
>name : Symbol(name, Decl(dependentReturnType10.ts, 11, 15))
|
||||
>greeting : Symbol(greeting, Decl(dependentReturnType10.ts, 11, 34))
|
||||
>breed : Symbol(breed, Decl(dependentReturnType10.ts, 11, 52))
|
||||
|
||||
never;
|
||||
|
||||
function greet<T extends string | Dog>(animal: T): GreetRet<T> {
|
||||
>greet : Symbol(greet, Decl(dependentReturnType10.ts, 12, 10))
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15))
|
||||
>Dog : Symbol(Dog, Decl(dependentReturnType10.ts, 3, 1))
|
||||
>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39))
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15))
|
||||
>GreetRet : Symbol(GreetRet, Decl(dependentReturnType10.ts, 7, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType10.ts, 14, 15))
|
||||
|
||||
if (typeof animal === "string") {
|
||||
>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39))
|
||||
|
||||
return `hello, ${animal}`
|
||||
>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39))
|
||||
}
|
||||
return { greeting: `woof, ${animal.name}`, breed: animal.breed }
|
||||
>greeting : Symbol(greeting, Decl(dependentReturnType10.ts, 18, 12))
|
||||
>animal.name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18))
|
||||
>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39))
|
||||
>name : Symbol(Animal.name, Decl(dependentReturnType10.ts, 0, 18))
|
||||
>breed : Symbol(breed, Decl(dependentReturnType10.ts, 18, 46))
|
||||
>animal.breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30))
|
||||
>animal : Symbol(animal, Decl(dependentReturnType10.ts, 14, 39))
|
||||
>breed : Symbol(Dog.breed, Decl(dependentReturnType10.ts, 5, 30))
|
||||
}
|
||||
78
tests/baselines/reference/dependentReturnType10.types
Normal file
78
tests/baselines/reference/dependentReturnType10.types
Normal file
@ -0,0 +1,78 @@
|
||||
//// [tests/cases/compiler/dependentReturnType10.ts] ////
|
||||
|
||||
=== dependentReturnType10.ts ===
|
||||
interface Animal {
|
||||
name: string;
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
|
||||
species: string;
|
||||
>species : string
|
||||
> : ^^^^^^
|
||||
}
|
||||
|
||||
interface Dog extends Animal {
|
||||
breed: string;
|
||||
>breed : string
|
||||
> : ^^^^^^
|
||||
}
|
||||
|
||||
type GreetRet<T> =
|
||||
>GreetRet : GreetRet<T>
|
||||
> : ^^^^^^^^^^^
|
||||
|
||||
T extends string ? string :
|
||||
T extends { name: string } ? { greeting: string, breed: string } :
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
>greeting : string
|
||||
> : ^^^^^^
|
||||
>breed : string
|
||||
> : ^^^^^^
|
||||
|
||||
never;
|
||||
|
||||
function greet<T extends string | Dog>(animal: T): GreetRet<T> {
|
||||
>greet : <T extends string | Dog>(animal: T) => GreetRet<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>animal : T
|
||||
> : ^
|
||||
|
||||
if (typeof animal === "string") {
|
||||
>typeof animal === "string" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof animal : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>animal : T
|
||||
> : ^
|
||||
>"string" : "string"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return `hello, ${animal}`
|
||||
>`hello, ${animal}` : string
|
||||
> : ^^^^^^
|
||||
>animal : T & string
|
||||
> : ^^^^^^^^^^
|
||||
}
|
||||
return { greeting: `woof, ${animal.name}`, breed: animal.breed }
|
||||
>{ greeting: `woof, ${animal.name}`, breed: animal.breed } : { greeting: string; breed: string; }
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>greeting : string
|
||||
> : ^^^^^^
|
||||
>`woof, ${animal.name}` : string
|
||||
> : ^^^^^^
|
||||
>animal.name : string
|
||||
> : ^^^^^^
|
||||
>animal : Dog
|
||||
> : ^^^
|
||||
>name : string
|
||||
> : ^^^^^^
|
||||
>breed : string
|
||||
> : ^^^^^^
|
||||
>animal.breed : string
|
||||
> : ^^^^^^
|
||||
>animal : Dog
|
||||
> : ^^^
|
||||
>breed : string
|
||||
> : ^^^^^^
|
||||
}
|
||||
22
tests/cases/compiler/dependentReturnType10.ts
Normal file
22
tests/cases/compiler/dependentReturnType10.ts
Normal file
@ -0,0 +1,22 @@
|
||||
// @noEmit: true
|
||||
|
||||
interface Animal {
|
||||
name: string;
|
||||
species: string;
|
||||
}
|
||||
|
||||
interface Dog extends Animal {
|
||||
breed: string;
|
||||
}
|
||||
|
||||
type GreetRet<T> =
|
||||
T extends string ? string :
|
||||
T extends { name: string } ? { greeting: string, breed: string } :
|
||||
never;
|
||||
|
||||
function greet<T extends string | Dog>(animal: T): GreetRet<T> {
|
||||
if (typeof animal === "string") {
|
||||
return `hello, ${animal}`
|
||||
}
|
||||
return { greeting: `woof, ${animal.name}`, breed: animal.breed }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user