TypeScript索引的访问类型约束行为异常

TypeScript索引的访问类型约束行为异常,typescript,generics,type-constraints,discriminated-union,Typescript,Generics,Type Constraints,Discriminated Union,就拿这个例子来说 接口人{ 姓名:TName ;; } 类型人= |人 |人 类型FilteredPersonBase=TPerson[“name”]扩展了“Levi”?特珀森:从来没有; 键入FilteredPerson=FilteredPersonBase;//从未 类型FilteredPersonBase2=TPerson扩展{name:“Levi”}?特珀森:从来没有; 类型FilteredPerson2=FilteredPersonBase2;//人 我希望FilteredPerso

就拿这个例子来说

接口人{
姓名:TName ;;
}
类型人=
|人
|人
类型FilteredPersonBase=TPerson[“name”]扩展了“Levi”?特珀森:从来没有;
键入FilteredPerson=FilteredPersonBase;//从未
类型FilteredPersonBase2=TPerson扩展{name:“Levi”}?特珀森:从来没有;
类型FilteredPerson2=FilteredPersonBase2;//人

我希望
FilteredPerson
FilteredPerson2
都能解析为
Person
,但它们没有。为什么在类型约束中使用索引访问操作符的解析方式与使用内联类型的解析方式不同?

我同意第二个应该解析为person
person
,但让我们看看是如何实现的:

FilteredPersonBase2<People>
    // FilteredPersonBase2 is a distributive conditional type since
    // TPerson appears nakedly in the condition of the conditional type
    => FilteredPersonBase2<Person<"Levi">> | FilteredPersonBase2<Person<"Julien">>
    // The conditional type is applied to each member of the union
    => (Person<"Levi"> extends { name: "Levi" } ? Person<"Levi"> : never) |  (Person<"Julien"> extends { name: "Levi" } ? Person<"Julien"> : never)
    // The first application return Person<"Levi">, the second resolves to never
    => Person<"Levi"> | never
    // Never is removed in a union 
    => Person<"Levi">
由于不进行分配,
TPerson[“name”]
只解析为
“Levi”|“Julien”
,而联合并不扩展组成部分。反之亦然(
“Levi”扩展了TPerson[“name”]
),但这只会解决工会(
),因为工会的一个组成部分是工会的一个子类型

为了好玩,您可以使用一个始终为真的条件(如
TPerson扩展TPerson
)强制对
TPerson
进行分发:

type FilteredPersonBase<TPerson extends People> = TPerson extends TPerson ? TPerson["name"] extends "Levi" ? TPerson : never : never;
type FilteredPerson = FilteredPersonBase<People>;  // Person<"Levi">
type FilteredPersonBase=TPerson扩展TPerson?TPerson[“name”]扩展了“Levi”?特珀森:永远:永远;
键入FilteredPerson=FilteredPersonBase;//人
type FilteredPersonBase<TPerson extends People> = TPerson extends TPerson ? TPerson["name"] extends "Levi" ? TPerson : never : never;
type FilteredPerson = FilteredPersonBase<People>;  // Person<"Levi">