diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go
index f3ccc9f04e1..bd6eb44dbcd 100644
--- a/tsc/internal/checker/checker.go
+++ b/tsc/internal/checker/checker.go
@@ -152,6 +152,11 @@ type CachedTypeKey struct {
typeId TypeId
}
+type DistributiveInstantiationKey struct {
+ typeId TypeId
+ typeParameterId TypeId
+}
+
// NarrowedTypeKey
type NarrowedTypeKey struct {
@@ -651,6 +656,7 @@ type Checker struct {
thisExpandoLocations map[*ast.Symbol]*ast.Node
subtypeReductionCache map[CacheHashKey][]*Type
cachedTypes map[CachedTypeKey]*Type
+ distributiveInstantiationCache map[DistributiveInstantiationKey]bool
cachedSignatures map[CachedSignatureKey]*Signature
undefinedProperties map[*ast.Symbol]*ast.Symbol
narrowedTypes map[NarrowedTypeKey]*Type
@@ -990,6 +996,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) {
c.thisExpandoLocations = make(map[*ast.Symbol]*ast.Node)
c.subtypeReductionCache = make(map[CacheHashKey][]*Type)
c.cachedTypes = make(map[CachedTypeKey]*Type)
+ c.distributiveInstantiationCache = make(map[DistributiveInstantiationKey]bool)
c.cachedSignatures = make(map[CachedSignatureKey]*Signature)
c.undefinedProperties = make(map[*ast.Symbol]*ast.Symbol)
c.narrowedTypes = make(map[NarrowedTypeKey]*Type)
diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go
index 5db176bc2b0..c8c41a2d8f3 100644
--- a/tsc/internal/checker/relater.go
+++ b/tsc/internal/checker/relater.go
@@ -3616,8 +3616,8 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo
nameType := r.c.getNameTypeFromMappedType(targetType)
constraintType := r.c.getConstraintTypeFromMappedType(targetType)
var targetKeys *Type
- isFiltering := nameType != nil && r.c.isMappedTypeWithKeyofConstraintDeclaration(targetType)
- if isFiltering {
+ isRemappedKeyof := nameType != nil && r.c.isMappedTypeWithKeyofConstraintDeclaration(targetType)
+ if isRemappedKeyof {
// we need to get the apparent mappings and union them with the generic mappings, since some properties may be
// missing from the `constraintType` which will otherwise be mapped in the object
mappedKeys := r.c.getApparentMappedTypeKeys(nameType, targetType)
@@ -3628,15 +3628,14 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo
} else {
targetKeys = constraintType
}
- if isFiltering && source.flags&TypeFlagsIntersection != 0 && r.someTypeRelatedToType(source, constraintType, false, intersectionState) == TernaryTrue {
- // run the filter over `source` - some part of `source` is related to the constraint - if source's other elements end up filtering the same way the nameType does, the assignment can pass
- // This effectively is a workaround for a lack of distributive conditional/distributive homomorphic mapped types relationship rules that uses execution of the distribution (even at higher order)
- // to approximate a better result.
- // See the homomorphic case in tsc\testdata\tests\cases\compiler\indexMappedTypeWithFilteredKeysWithNegation.ts
- sourceInstantiatedTarget := r.c.instantiateType(nameType, newSimpleTypeMapper(r.c.getTypeParameterFromMappedType(targetType), source))
- broadTargetKeys := r.c.getUnionType([]*Type{targetKeys, sourceInstantiatedTarget})
- if r.isRelatedTo(source, broadTargetKeys, RecursionFlagsTarget, false) == TernaryTrue {
- return TernaryTrue
+ if isRemappedKeyof && source.flags&TypeFlagsIntersection != 0 {
+ if filteredNameType := r.getOptionalSimplificationOfConditional(nameType); filteredNameType != nil && r.someTypeRelatedToType(source, constraintType, false, intersectionState) == TernaryTrue {
+ // Apply the filter only to a source already constrained to the mapped keys.
+ sourceInstantiatedTarget := r.c.instantiateType(filteredNameType, newSimpleTypeMapper(r.c.getTypeParameterFromMappedType(targetType), source))
+ broadTargetKeys := r.c.getUnionType([]*Type{targetKeys, sourceInstantiatedTarget})
+ if r.isRelatedTo(source, broadTargetKeys, RecursionFlagsTarget, false) == TernaryTrue {
+ return TernaryTrue
+ }
}
}
if r.isRelatedTo(source, targetKeys, RecursionFlagsTarget, reportErrors) == TernaryTrue {
@@ -4024,32 +4023,72 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo
return TernaryFalse
}
+// TODO: Replace this heuristic with proper distributive conditional type relationship rules.
+// For a distributive A extends B ? never : Q without infer parameters, rewrite to Q.
+// A definitely false check uses Q unchanged; a definitely true check cannot use the rewrite.
+// Otherwise B must be independent of A, and Q must be never. The conditional already distributes,
+// but we also probe whether Q agrees with Q | Q before moving the union inside Q.
+// See Repeated in indexMappedTypeWithFilteredKeysWithNegationErrors.ts, where moving the union
+// inside `${A}-${A}` would lose the correlation between occurrences of A.
func (r *Relater) getOptionalSimplificationOfConditional(target *Type) *Type {
if target.flags&TypeFlagsConditional == 0 {
return nil
}
- // TODO: This is a kludge for not having proper rules for relating distributive conditional types.
- // We rewrite `A extends B ? never : Q` into `Q` - provided that substitution
- // actually changes it. This is not *particularly* accurate, but enables the common case of relating a filtering mapped type to the equivalent filtering negated type.
- // See the non-homomorphic case in tsc\testdata\tests\cases\compiler\indexMappedTypeWithFilteredKeysWithNegation.ts for an example.
- root := target.AsConditionalType().root
- if root.isDistributive && r.c.getTrueTypeFromConditionalType(target).flags&TypeFlagsNever != 0 {
- f := r.c.getFalseTypeFromConditionalType(target)
- remappedFalseType := r.c.instantiateType(
- r.c.getTypeFromTypeNode(root.node.FalseType),
- r.c.combineTypeMappers(
- newSimpleTypeMapper(
- getNonDistributedTypeParameter(root.checkType),
- r.c.getIntersectionType([]*Type{root.checkType, r.c.getNegatedType(root.extendsType)}),
- ),
- target.AsConditionalType().mapper,
- ),
- )
- if remappedFalseType != f {
- return remappedFalseType
- }
+ conditional := target.AsConditionalType()
+ root := conditional.root
+ if !root.isDistributive || len(root.inferTypeParameters) != 0 || r.c.getTrueTypeFromConditionalType(target).flags&TypeFlagsNever == 0 {
+ return nil
}
- return nil
+ permissiveExtendsType := r.c.getPermissiveInstantiation(conditional.extendsType)
+ skipTrue := !someType(r.c.getPermissiveInstantiation(conditional.checkType), func(t *Type) bool {
+ return r.c.isTypeAssignableTo(t, permissiveExtendsType)
+ })
+ if skipTrue {
+ return r.c.getFalseTypeFromConditionalType(target)
+ }
+ if r.c.isTypeAssignableTo(r.c.getRestrictiveInstantiation(conditional.checkType), r.c.getRestrictiveInstantiation(conditional.extendsType)) {
+ return nil
+ }
+ checkType := getNonDistributedTypeParameter(root.checkType)
+ if r.c.isTypeParameterPossiblyReferenced(checkType, root.node.ExtendsType) {
+ return nil
+ }
+ falseType := r.c.getTypeFromTypeNode(root.node.FalseType)
+ if !r.canDistributeTypeInstantiation(falseType, checkType) {
+ return nil
+ }
+ return r.c.instantiateType(
+ falseType,
+ r.c.combineTypeMappers(
+ newSimpleTypeMapper(checkType, r.c.getIntersectionType([]*Type{root.checkType, r.c.getNegatedType(root.extendsType)})),
+ conditional.mapper,
+ ),
+ )
+}
+
+func (r *Relater) canDistributeTypeInstantiation(t *Type, typeParameter *Type) bool {
+ key := DistributiveInstantiationKey{typeId: t.id, typeParameterId: typeParameter.id}
+ if result, ok := r.c.distributiveInstantiationCache[key]; ok {
+ return result
+ }
+ // A recursive probe is unproven until the outer comparison completes.
+ r.c.distributiveInstantiationCache[key] = false
+ // Filtering can remove the entire check type, so the false branch must also preserve never.
+ if r.c.instantiateType(t, newSimpleTypeMapper(typeParameter, r.c.neverType)).flags&TypeFlagsNever == 0 {
+ return false
+ }
+ left := r.c.markerSuperType
+ right := r.c.markerOtherType
+ instantiate := func(argument *Type) *Type {
+ return r.c.getSimplifiedType(r.c.instantiateType(t, newSimpleTypeMapper(typeParameter, argument)), false /*writing*/)
+ }
+ // Require execution over unrelated union members to agree with distributing first.
+ // Use the existing identity comparison rather than introducing conditional relationship rules.
+ instantiatedUnion := instantiate(r.c.getUnionType([]*Type{left, right}))
+ unionOfInstantiations := r.c.getUnionType([]*Type{instantiate(left), instantiate(right)})
+ result := r.c.isTypeIdenticalTo(instantiatedUnion, unionOfInstantiations)
+ r.c.distributiveInstantiationCache[key] = result
+ return result
}
func (r *Relater) typeArgumentsRelatedTo(sources []*Type, targets []*Type, variances []VarianceFlags, reportErrors bool, intersectionState IntersectionState) Ternary {
diff --git a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.js b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.js
index 089cb2ff363..bd0ec8a4a61 100644
--- a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.js
+++ b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.js
@@ -39,6 +39,102 @@ const t1: T1 = ['b', 'c'];
type S1 = { [K in keyof T & string as K extends '_key' ? never : K]: 1 }[LocalExclude];
type S2 = { [K in string & keyof T as K extends '_key' ? never : K]: 1 }[LocalExclude];
+
+type ConditionalExclude = T extends U ? never : T;
+
+function exclude(value: T & not U): ConditionalExclude {
+ return value;
+}
+
+type Identity = T;
+type AliasedExclude = T extends U ? never : Identity;
+
+function aliasedExclude(value: T & not U): AliasedExclude {
+ return value;
+}
+
+function mappedExclude(value: keyof T & not U): keyof ExcludeKey {
+ return value;
+}
+
+type AliasedExcludeKey = {
+ [K in keyof T as ConditionalExclude]: T[K]
+};
+
+function aliasedMappedExclude(value: keyof T & not U): keyof AliasedExcludeKey {
+ return value;
+}
+
+type Prefixed = T extends "skip" ? never : `prefix${T}`;
+
+function prefixed(value: `prefix${T & not "skip"}`): Prefixed {
+ return value;
+}
+
+type WithSuffix = T extends "skip" ? never : `prefix${T}:${S}`;
+
+function withSuffix(value: `prefix${T & not "skip"}:${S}`): WithSuffix {
+ return value;
+}
+
+type Cased = Uppercase<`prefix${Lowercase}`>;
+type FilteredCased = T extends "skip" ? never : Cased;
+
+function cased(value: Cased): FilteredCased {
+ return value;
+}
+
+type Alternatives = T extends "skip" ? never : `left${T}` | `right${Uppercase}`;
+
+function alternatives(
+ value: `left${T & not "skip"}` | `right${Uppercase}`
+): Alternatives {
+ return value;
+}
+
+type Branded = T extends "skip" ? never : T & { brand: true };
+
+function branded(value: T & not "skip" & { brand: true }): Branded {
+ return value;
+}
+
+interface Values {
+ a: 1;
+ b: 2;
+ skip: 3;
+}
+
+type Lookup = T extends "skip" ? never : Values[T];
+
+function lookup(value: Values[T & not "skip"]): Lookup {
+ return value;
+}
+
+type PrefixedKeys = {
+ [K in keyof T & string as K extends "_key" ? never : `prefix${K}`]: T[K]
+};
+
+function prefixedKey(value: `prefix${keyof T & string & not "_key"}`): keyof PrefixedKeys {
+ return value;
+}
+
+type FunctionResult = T extends string ? never : () => T;
+
+function falseFunction(value: () => [T]): FunctionResult<[T]> {
+ return value;
+}
+
+type TupleResult = T extends string ? never : [T, T];
+
+function falseTuple(value: [[T], [T]]): TupleResult<[T]> {
+ return value;
+}
+
+type Nested = T extends "skip" ? never : ConditionalExclude<`prefix${T}`, "prefixomit">;
+
+function nested(value: ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">): Nested {
+ return value;
+}
//// [indexMappedTypeWithFilteredKeysWithNegation.js]
@@ -48,3 +144,45 @@ function f(test, possibleKey) {
test[possibleKey];
}
const t1 = ['b', 'c'];
+function exclude(value) {
+ return value;
+}
+function aliasedExclude(value) {
+ return value;
+}
+function mappedExclude(value) {
+ return value;
+}
+function aliasedMappedExclude(value) {
+ return value;
+}
+function prefixed(value) {
+ return value;
+}
+function withSuffix(value) {
+ return value;
+}
+function cased(value) {
+ return value;
+}
+function alternatives(value) {
+ return value;
+}
+function branded(value) {
+ return value;
+}
+function lookup(value) {
+ return value;
+}
+function prefixedKey(value) {
+ return value;
+}
+function falseFunction(value) {
+ return value;
+}
+function falseTuple(value) {
+ return value;
+}
+function nested(value) {
+ return value;
+}
diff --git a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.symbols b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.symbols
index 0480638a442..5a5380e5710 100644
--- a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.symbols
+++ b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.symbols
@@ -137,3 +137,334 @@ type S2 = { [K in string & keyof T as K extends '_key' ? never : K]: 1 }[Loca
>LocalExclude : Symbol(LocalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 18, 1))
>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 8))
+type ConditionalExclude = T extends U ? never : T;
+>ConditionalExclude : Symbol(ConditionalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 116))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 24))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 26))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 24))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 26))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 24))
+
+function exclude(value: T & not U): ConditionalExclude {
+>exclude : Symbol(exclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 39, 56))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 17))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 19))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 23))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 17))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 19))
+>ConditionalExclude : Symbol(ConditionalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 116))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 17))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 19))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 41, 23))
+}
+
+type Identity = T;
+>Identity : Symbol(Identity, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 43, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 45, 14))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 45, 14))
+
+type AliasedExclude = T extends U ? never : Identity;
+>AliasedExclude : Symbol(AliasedExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 45, 21))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 20))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 22))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 20))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 22))
+>Identity : Symbol(Identity, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 43, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 20))
+
+function aliasedExclude(value: T & not U): AliasedExclude {
+>aliasedExclude : Symbol(aliasedExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 46, 62))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 24))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 26))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 30))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 24))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 26))
+>AliasedExclude : Symbol(AliasedExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 45, 21))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 24))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 26))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 48, 30))
+}
+
+function mappedExclude(value: keyof T & not U): keyof ExcludeKey {
+>mappedExclude : Symbol(mappedExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 50, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 23))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 25))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 29))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 23))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 25))
+>ExcludeKey : Symbol(ExcludeKey, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 0, 0))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 23))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 25))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 52, 29))
+}
+
+type AliasedExcludeKey = {
+>AliasedExcludeKey : Symbol(AliasedExcludeKey, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 54, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 56, 23))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 56, 25))
+
+ [K in keyof T as ConditionalExclude]: T[K]
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 57, 5))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 56, 23))
+>ConditionalExclude : Symbol(ConditionalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 116))
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 57, 5))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 56, 25))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 56, 23))
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 57, 5))
+
+};
+
+function aliasedMappedExclude(value: keyof T & not U): keyof AliasedExcludeKey {
+>aliasedMappedExclude : Symbol(aliasedMappedExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 58, 2))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 30))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 32))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 36))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 30))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 32))
+>AliasedExcludeKey : Symbol(AliasedExcludeKey, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 54, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 30))
+>U : Symbol(U, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 32))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 60, 36))
+}
+
+type Prefixed = T extends "skip" ? never : `prefix${T}`;
+>Prefixed : Symbol(Prefixed, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 62, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 64, 14))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 64, 14))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 64, 14))
+
+function prefixed(value: `prefix${T & not "skip"}`): Prefixed {
+>prefixed : Symbol(prefixed, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 64, 74))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 66, 18))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 66, 36))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 66, 18))
+>Prefixed : Symbol(Prefixed, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 62, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 66, 18))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 66, 36))
+}
+
+type WithSuffix = T extends "skip" ? never : `prefix${T}:${S}`;
+>WithSuffix : Symbol(WithSuffix, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 68, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 16))
+>S : Symbol(S, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 33))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 16))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 16))
+>S : Symbol(S, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 33))
+
+function withSuffix(value: `prefix${T & not "skip"}:${S}`): WithSuffix {
+>withSuffix : Symbol(withSuffix, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 70, 99))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 20))
+>S : Symbol(S, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 37))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 56))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 20))
+>S : Symbol(S, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 37))
+>WithSuffix : Symbol(WithSuffix, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 68, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 20))
+>S : Symbol(S, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 37))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 72, 56))
+}
+
+type Cased = Uppercase<`prefix${Lowercase}`>;
+>Cased : Symbol(Cased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 74, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 76, 11))
+>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
+>Lowercase : Symbol(Lowercase, Decl(lib.es5.d.ts, --, --))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 76, 11))
+
+type FilteredCased = T extends "skip" ? never : Cased;
+>FilteredCased : Symbol(FilteredCased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 76, 66))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 77, 19))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 77, 19))
+>Cased : Symbol(Cased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 74, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 77, 19))
+
+function cased(value: Cased): FilteredCased {
+>cased : Symbol(cased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 77, 75))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 79, 15))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 79, 33))
+>Cased : Symbol(Cased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 74, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 79, 15))
+>FilteredCased : Symbol(FilteredCased, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 76, 66))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 79, 15))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 79, 33))
+}
+
+type Alternatives = T extends "skip" ? never : `left${T}` | `right${Uppercase}`;
+>Alternatives : Symbol(Alternatives, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 81, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 83, 18))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 83, 18))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 83, 18))
+>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 83, 18))
+
+function alternatives(
+>alternatives : Symbol(alternatives, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 83, 101))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 22))
+
+ value: `left${T & not "skip"}` | `right${Uppercase}`
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 40))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 22))
+>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 22))
+
+): Alternatives {
+>Alternatives : Symbol(Alternatives, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 81, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 22))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 85, 40))
+}
+
+type Branded = T extends "skip" ? never : T & { brand: true };
+>Branded : Symbol(Branded, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 89, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 91, 13))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 91, 13))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 91, 13))
+>brand : Symbol(brand, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 91, 50))
+
+function branded(value: T & not "skip" & { brand: true }): Branded {
+>branded : Symbol(branded, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 91, 65))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 17))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 20))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 17))
+>brand : Symbol(brand, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 45))
+>Branded : Symbol(Branded, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 89, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 17))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 93, 20))
+}
+
+interface Values {
+>Values : Symbol(Values, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 95, 1))
+
+ a: 1;
+>a : Symbol(Values.a, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 97, 18))
+
+ b: 2;
+>b : Symbol(Values.b, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 98, 9))
+
+ skip: 3;
+>skip : Symbol(Values.skip, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 99, 9))
+}
+
+type Lookup = T extends "skip" ? never : Values[T];
+>Lookup : Symbol(Lookup, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 101, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 103, 12))
+>Values : Symbol(Values, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 95, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 103, 12))
+>Values : Symbol(Values, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 95, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 103, 12))
+
+function lookup(value: Values[T & not "skip"]): Lookup {
+>lookup : Symbol(lookup, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 103, 75))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 105, 16))
+>Values : Symbol(Values, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 95, 1))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 105, 40))
+>Values : Symbol(Values, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 95, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 105, 16))
+>Lookup : Symbol(Lookup, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 101, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 105, 16))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 105, 40))
+}
+
+type PrefixedKeys = {
+>PrefixedKeys : Symbol(PrefixedKeys, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 107, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 109, 18))
+
+ [K in keyof T & string as K extends "_key" ? never : `prefix${K}`]: T[K]
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 110, 5))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 109, 18))
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 110, 5))
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 110, 5))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 109, 18))
+>K : Symbol(K, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 110, 5))
+
+};
+
+function prefixedKey(value: `prefix${keyof T & string & not "_key"}`): keyof PrefixedKeys {
+>prefixedKey : Symbol(prefixedKey, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 111, 2))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 113, 21))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 113, 24))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 113, 21))
+>PrefixedKeys : Symbol(PrefixedKeys, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 107, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 113, 21))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 113, 24))
+}
+
+type FunctionResult = T extends string ? never : () => T;
+>FunctionResult : Symbol(FunctionResult, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 115, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 117, 20))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 117, 20))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 117, 20))
+
+function falseFunction(value: () => [T]): FunctionResult<[T]> {
+>falseFunction : Symbol(falseFunction, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 117, 60))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 119, 23))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 119, 26))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 119, 23))
+>FunctionResult : Symbol(FunctionResult, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 115, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 119, 23))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 119, 26))
+}
+
+type TupleResult = T extends string ? never : [T, T];
+>TupleResult : Symbol(TupleResult, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 121, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 123, 17))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 123, 17))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 123, 17))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 123, 17))
+
+function falseTuple(value: [[T], [T]]): TupleResult<[T]> {
+>falseTuple : Symbol(falseTuple, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 123, 56))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 20))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 23))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 20))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 20))
+>TupleResult : Symbol(TupleResult, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 121, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 20))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 125, 23))
+}
+
+type Nested = T extends "skip" ? never : ConditionalExclude<`prefix${T}`, "prefixomit">;
+>Nested : Symbol(Nested, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 127, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 129, 12))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 129, 12))
+>ConditionalExclude : Symbol(ConditionalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 116))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 129, 12))
+
+function nested(value: ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">): Nested {
+>nested : Symbol(nested, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 129, 106))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 131, 16))
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 131, 34))
+>ConditionalExclude : Symbol(ConditionalExclude, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 37, 116))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 131, 16))
+>Nested : Symbol(Nested, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 127, 1))
+>T : Symbol(T, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 131, 16))
+
+ return value;
+>value : Symbol(value, Decl(indexMappedTypeWithFilteredKeysWithNegation.ts, 131, 34))
+}
+
diff --git a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.types b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.types
index df04ec5a817..414a259a75d 100644
--- a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.types
+++ b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegation.types
@@ -79,3 +79,184 @@ type S1 = { [K in keyof T & string as K extends '_key' ? never : K]: 1 }[Loca
type S2 = { [K in string & keyof T as K extends '_key' ? never : K]: 1 }[LocalExclude];
>S2 : S2
+type ConditionalExclude = T extends U ? never : T;
+>ConditionalExclude : ConditionalExclude
+
+function exclude(value: T & not U): ConditionalExclude {
+>exclude : (value: T & not U) => ConditionalExclude
+>value : T & not U
+
+ return value;
+>value : T & not U
+}
+
+type Identity = T;
+>Identity : T
+
+type AliasedExclude = T extends U ? never : Identity;
+>AliasedExclude : AliasedExclude
+
+function aliasedExclude(value: T & not U): AliasedExclude {
+>aliasedExclude : (value: T & not U) => AliasedExclude
+>value : T & not U
+
+ return value;
+>value : T & not U
+}
+
+function mappedExclude(value: keyof T & not U): keyof ExcludeKey {
+>mappedExclude : (value: keyof T & not U) => keyof ExcludeKey
+>value : keyof T & not U
+
+ return value;
+>value : keyof T & not U
+}
+
+type AliasedExcludeKey = {
+>AliasedExcludeKey : AliasedExcludeKey
+
+ [K in keyof T as ConditionalExclude]: T[K]
+};
+
+function aliasedMappedExclude(value: keyof T & not U): keyof AliasedExcludeKey {
+>aliasedMappedExclude : (value: keyof T & not U) => keyof AliasedExcludeKey
+>value : keyof T & not U
+
+ return value;
+>value : keyof T & not U
+}
+
+type Prefixed = T extends "skip" ? never : `prefix${T}`;
+>Prefixed : Prefixed
+
+function prefixed(value: `prefix${T & not "skip"}`): Prefixed {
+>prefixed : (value: `prefix${T & not "skip"}`) => Prefixed
+>value : `prefix${T & not "skip"}`
+
+ return value;
+>value : `prefix${T & not "skip"}`
+}
+
+type WithSuffix = T extends "skip" ? never : `prefix${T}:${S}`;
+>WithSuffix : WithSuffix
+
+function withSuffix(value: `prefix${T & not "skip"}:${S}`): WithSuffix {
+>withSuffix : (value: `prefix${T & not "skip"}:${S}`) => WithSuffix
+>value : `prefix${T & not "skip"}:${S}`
+
+ return value;
+>value : `prefix${T & not "skip"}:${S}`
+}
+
+type Cased = Uppercase<`prefix${Lowercase}`>;
+>Cased : `PREFIX${Uppercase>}`
+
+type FilteredCased = T extends "skip" ? never : Cased;
+>FilteredCased : FilteredCased
+
+function cased(value: Cased): FilteredCased {
+>cased : (value: Cased) => FilteredCased
+>value : `PREFIX${Uppercase>}`
+
+ return value;
+>value : `PREFIX${Uppercase>}`
+}
+
+type Alternatives = T extends "skip" ? never : `left${T}` | `right${Uppercase}`;
+>Alternatives : Alternatives
+
+function alternatives(
+>alternatives : (value: `left${T & not "skip"}` | `right${Uppercase}`) => Alternatives
+
+ value: `left${T & not "skip"}` | `right${Uppercase}`
+>value : `left${T & not "skip"}` | `right${Uppercase}`
+
+): Alternatives {
+ return value;
+>value : `left${T & not "skip"}` | `right${Uppercase}`
+}
+
+type Branded = T extends "skip" ? never : T & { brand: true };
+>Branded : Branded
+>brand : true
+>true : true
+
+function branded(value: T & not "skip" & { brand: true }): Branded {
+>branded : (value: T & not "skip" & { brand: true; }) => Branded
+>value : T & not "skip" & { brand: true; }
+>brand : true
+>true : true
+
+ return value;
+>value : T & not "skip" & { brand: true; }
+}
+
+interface Values {
+ a: 1;
+>a : 1
+
+ b: 2;
+>b : 2
+
+ skip: 3;
+>skip : 3
+}
+
+type Lookup = T extends "skip" ? never : Values[T];
+>Lookup : Lookup
+
+function lookup(value: Values[T & not "skip"]): Lookup {
+>lookup : (value: Values[T & not "skip"]) => Lookup
+>value : Values[T & not "skip"]
+
+ return value;
+>value : Values[T & not "skip"]
+}
+
+type PrefixedKeys = {
+>PrefixedKeys : PrefixedKeys
+
+ [K in keyof T & string as K extends "_key" ? never : `prefix${K}`]: T[K]
+};
+
+function prefixedKey(value: `prefix${keyof T & string & not "_key"}`): keyof PrefixedKeys {
+>prefixedKey : (value: `prefix${keyof T & string & not "_key"}`) => keyof PrefixedKeys
+>value : `prefix${keyof T & string & not "_key"}`
+
+ return value;
+>value : `prefix${keyof T & string & not "_key"}`
+}
+
+type FunctionResult = T extends string ? never : () => T;
+>FunctionResult : FunctionResult
+
+function falseFunction(value: () => [T]): FunctionResult<[T]> {
+>falseFunction : (value: () => [T]) => FunctionResult<[T]>
+>value : () => [T]
+
+ return value;
+>value : () => [T]
+}
+
+type TupleResult = T extends string ? never : [T, T];
+>TupleResult : TupleResult
+
+function falseTuple(value: [[T], [T]]): TupleResult<[T]> {
+>falseTuple : (value: [[T], [T]]) => TupleResult<[T]>
+>value : [[T], [T]]
+
+ return value;
+>value : [[T], [T]]
+}
+
+type Nested = T extends "skip" ? never : ConditionalExclude<`prefix${T}`, "prefixomit">;
+>Nested : Nested
+
+function nested(value: ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">): Nested {
+>nested : (value: ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">) => Nested
+>value : ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">
+
+ return value;
+>value : ConditionalExclude<`prefix${T & not "skip"}`, "prefixomit">
+}
+
diff --git a/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegationErrors.errors.txt b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegationErrors.errors.txt
new file mode 100644
index 00000000000..252365eef68
--- /dev/null
+++ b/tsc/testdata/baselines/reference/compiler/indexMappedTypeWithFilteredKeysWithNegationErrors.errors.txt
@@ -0,0 +1,148 @@
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(5,5): error TS2322: Type '() => never' is not assignable to type 'FilteredFunction'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(14,5): error TS2322: Type '[T & not false & not true, T & not false & not true]' is not assignable to type 'FilteredPair'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(24,5): error TS2322: Type 'T & not Omitted' is not assignable to type 'DependentFilter'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(33,5): error TS2322: Type 'T' is not assignable to type 'Filter'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(42,5): error TS2322: Type 'keyof T & not "c"' is not assignable to type 'keyof FilteredKeys'.
+ Type 'keyof T & not "c"' is not assignable to type 'K extends "b" ? never : K'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(47,5): error TS2322: Type 'string & not "b"' is not assignable to type 'keyof FilteredKeys'.
+ Type 'string & not "b"' is not assignable to type 'K extends "b" ? never : K'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(58,5): error TS2322: Type 'keyof T & not "c"' is not assignable to type 'keyof RemappedKeys'.
+ Type 'keyof T & not "c"' is not assignable to type '"a" | "b" extends K ? K : never'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(67,5): error TS2322: Type 'keyof T & not Omitted' is not assignable to type 'keyof DependentKeys'.
+ Type 'keyof T & not Omitted' is not assignable to type 'K extends Omitted ? never : K'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(74,5): error TS2322: Type '`${T & not "skip"}-${T & not "skip"}`' is not assignable to type 'Repeated'.
+ Type '`${string}-${string}`' is not assignable to type 'Repeated'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(83,5): error TS2322: Type 'T & not string & { value: T & not string; }' is not assignable to type 'Correlated'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(88,5): error TS2322: Type '() => string & { value: T; }' is not assignable to type 'never'.
+indexMappedTypeWithFilteredKeysWithNegationErrors.ts(93,5): error TS2322: Type '() => string | [T]' is not assignable to type '() => [T]'.
+ Type 'string | [T]' is not assignable to type '[T]'.
+ Type 'string' is not assignable to type '[T]'.
+
+
+==== indexMappedTypeWithFilteredKeysWithNegationErrors.ts (12 errors) ====
+ type FilteredFunction = T extends string ? never : () => T;
+
+ function makeFunction(): FilteredFunction {
+ // When T is string, FilteredFunction is never, but this still returns a function.
+ return () => { throw new Error(); };
+ ~~~~~~
+!!! error TS2322: Type '() => never' is not assignable to type 'FilteredFunction'.
+ }
+
+ const impossibleFunction: never = makeFunction();
+
+ type FilteredPair = T extends boolean ? never : [T, T];
+
+ function makePair(value: [T & not boolean, T & not boolean]): FilteredPair {
+ // The tuple elements can come from different union members, unlike the distributed FilteredPair.
+ return value;
+ ~~~~~~
+!!! error TS2322: Type '[T & not false & not true, T & not false & not true]' is not assignable to type 'FilteredPair'.
+ }
+
+ const homogeneousPair: [string, string] | [number, number] = makePair(["a", 1]);
+
+ type Omitted = "a" extends T ? never : "b";
+ type DependentFilter = T extends Omitted ? never : T;
+
+ function dependentFilter(value: T & not Omitted): DependentFilter {
+ // For T = "a" | "b", Omitted is never, so value can be "b", but DependentFilter is "a".
+ return value;
+ ~~~~~~
+!!! error TS2322: Type 'T & not Omitted' is not assignable to type 'DependentFilter'.
+ }
+
+ const onlyA: "a" = dependentFilter<"a" | "b">("b");
+
+ type Filter = T extends U ? never : T;
+
+ function unfiltered(value: T): Filter {
+ // value can still belong to U, whose members are excluded from Filter.
+ return value;
+ ~~~~~~
+!!! error TS2322: Type 'T' is not assignable to type 'Filter'.
+ }
+
+ type FilteredKeys = {
+ [K in keyof T as K extends "b" ? never : K]: T[K]
+ };
+
+ function excludedKey(value: keyof T & not "c"): keyof FilteredKeys {
+ // Excluding "c" does not prevent value from being the filtered-out key "b".
+ return value;
+ ~~~~~~
+!!! error TS2322: Type 'keyof T & not "c"' is not assignable to type 'keyof FilteredKeys'.
+!!! error TS2322: Type 'keyof T & not "c"' is not assignable to type 'K extends "b" ? never : K'.
+ }
+
+ function unrelatedKey(value: string & not "b"): keyof FilteredKeys {
+ // value is not constrained to keyof T and may name a property T does not have.
+ return value;
+ ~~~~~~
+!!! error TS2322: Type 'string & not "b"' is not assignable to type 'keyof FilteredKeys'.
+!!! error TS2322: Type 'string & not "b"' is not assignable to type 'K extends "b" ? never : K'.
+ }
+
+ type RemappedKeys