mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-09 07:55:10 -05:00
Merge pull request #22197 from Microsoft/fixConditionalTypes
Conditional type fixes
This commit is contained in:
@@ -318,7 +318,6 @@ namespace ts {
|
||||
const intersectionTypes = createMap<IntersectionType>();
|
||||
const literalTypes = createMap<LiteralType>();
|
||||
const indexedAccessTypes = createMap<IndexedAccessType>();
|
||||
const conditionalTypes = createMap<ConditionalType>();
|
||||
const evolvingArrayTypes: EvolvingArrayType[] = [];
|
||||
const undefinedProperties = createMap<Symbol>() as UnderscoreEscapedMap<Symbol>;
|
||||
|
||||
@@ -600,6 +599,7 @@ namespace ts {
|
||||
ObjectType = 1 << 9,
|
||||
EmptyObject = 1 << 10,
|
||||
Union = 1 << 11,
|
||||
Wildcard = 1 << 12,
|
||||
}
|
||||
|
||||
const enum MembersOrExportsResolutionKind {
|
||||
@@ -2975,8 +2975,8 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Conditional) {
|
||||
const checkTypeNode = typeToTypeNodeHelper((<ConditionalType>type).checkType, context);
|
||||
const extendsTypeNode = typeToTypeNodeHelper((<ConditionalType>type).extendsType, context);
|
||||
const trueTypeNode = typeToTypeNodeHelper((<ConditionalType>type).trueType, context);
|
||||
const falseTypeNode = typeToTypeNodeHelper((<ConditionalType>type).falseType, context);
|
||||
const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(<ConditionalType>type), context);
|
||||
const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(<ConditionalType>type), context);
|
||||
return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
|
||||
}
|
||||
if (type.flags & TypeFlags.Substitution) {
|
||||
@@ -5899,8 +5899,7 @@ namespace ts {
|
||||
// Create a mapper from T to the current iteration type constituent. Then, if the
|
||||
// mapped type is itself an instantiated type, combine the iteration mapper with the
|
||||
// instantiation mapper.
|
||||
const iterationMapper = createTypeMapper([typeParameter], [t]);
|
||||
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, iterationMapper) : iterationMapper;
|
||||
const templateMapper = combineTypeMappers(type.mapper, createTypeMapper([typeParameter], [t]));
|
||||
const propType = instantiateType(templateType, templateMapper);
|
||||
// If the current iteration type constituent is a string literal type, create a property.
|
||||
// Otherwise, for type string create a string index signature.
|
||||
@@ -6122,22 +6121,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDefaultConstraintOfConditionalType(type: ConditionalType) {
|
||||
return getUnionType([type.trueType, type.falseType]);
|
||||
return getUnionType([getTrueTypeFromConditionalType(type), getFalseTypeFromConditionalType(type)]);
|
||||
}
|
||||
|
||||
function getConstraintOfDistributiveConditionalType(type: ConditionalType) {
|
||||
function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type {
|
||||
// Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained
|
||||
// type parameter. If so, create an instantiation of the conditional type where T is replaced
|
||||
// with its constraint. We do this because if the constraint is a union type it will be distributed
|
||||
// over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T'
|
||||
// removes 'undefined' from T.
|
||||
if (isDistributiveConditionalType(type)) {
|
||||
if (type.root.isDistributive) {
|
||||
const constraint = getConstraintOfType(type.checkType);
|
||||
if (constraint) {
|
||||
const target = type.target || type;
|
||||
const mapper = createTypeMapper([<TypeParameter>target.checkType], [constraint]);
|
||||
const combinedMapper = type.mapper ? combineTypeMappers(mapper, type.mapper) : mapper;
|
||||
return instantiateType(target, combinedMapper);
|
||||
const mapper = createTypeMapper([<TypeParameter>type.root.checkType], [constraint]);
|
||||
return getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@@ -6236,7 +6233,8 @@ namespace ts {
|
||||
return baseIndexedAccess && baseIndexedAccess !== unknownType ? getBaseConstraint(baseIndexedAccess) : undefined;
|
||||
}
|
||||
if (t.flags & TypeFlags.Conditional) {
|
||||
return getBaseConstraint(getConstraintOfConditionalType(<ConditionalType>t));
|
||||
const constraint = getConstraintOfConditionalType(<ConditionalType>t);
|
||||
return constraint && getBaseConstraint(constraint);
|
||||
}
|
||||
if (t.flags & TypeFlags.Substitution) {
|
||||
return getBaseConstraint((<SubstitutionType>t).substitute);
|
||||
@@ -7639,6 +7637,7 @@ namespace ts {
|
||||
}
|
||||
else if (flags & TypeFlags.Any) {
|
||||
includes |= TypeIncludes.Any;
|
||||
if (type === wildcardType) includes |= TypeIncludes.Wildcard;
|
||||
}
|
||||
else if (!strictNullChecks && flags & TypeFlags.Nullable) {
|
||||
if (flags & TypeFlags.Undefined) includes |= TypeIncludes.Undefined;
|
||||
@@ -7758,7 +7757,7 @@ namespace ts {
|
||||
const typeSet: Type[] = [];
|
||||
const includes = addTypesToUnion(typeSet, 0, types);
|
||||
if (includes & TypeIncludes.Any) {
|
||||
return anyType;
|
||||
return includes & TypeIncludes.Wildcard ? wildcardType : anyType;
|
||||
}
|
||||
switch (unionReduction) {
|
||||
case UnionReduction.Literal:
|
||||
@@ -8140,7 +8139,7 @@ namespace ts {
|
||||
|
||||
function substituteIndexedMappedType(objectType: MappedType, type: IndexedAccessType) {
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [type.indexType]);
|
||||
const templateMapper = objectType.mapper ? combineTypeMappers(objectType.mapper, mapper) : mapper;
|
||||
const templateMapper = combineTypeMappers(objectType.mapper, mapper);
|
||||
return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper);
|
||||
}
|
||||
|
||||
@@ -8207,76 +8206,59 @@ namespace ts {
|
||||
return type.flags & TypeFlags.Substitution ? (<SubstitutionType>type).typeParameter : type;
|
||||
}
|
||||
|
||||
function createConditionalType(checkType: Type, extendsType: Type, trueType: Type, falseType: Type, inferTypeParameters: TypeParameter[], target: ConditionalType, mapper: TypeMapper, aliasSymbol: Symbol, aliasTypeArguments: Type[]) {
|
||||
const type = <ConditionalType>createType(TypeFlags.Conditional);
|
||||
type.checkType = checkType;
|
||||
type.extendsType = extendsType;
|
||||
type.trueType = trueType;
|
||||
type.falseType = falseType;
|
||||
type.inferTypeParameters = inferTypeParameters;
|
||||
type.target = target;
|
||||
type.mapper = mapper;
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
return type;
|
||||
}
|
||||
|
||||
function getConditionalType(checkType: Type, baseExtendsType: Type, baseTrueType: Type, baseFalseType: Type, inferTypeParameters: TypeParameter[], target: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, baseAliasTypeArguments?: Type[]): Type {
|
||||
// Instantiate extends type without instantiating any 'infer T' type parameters
|
||||
const extendsType = instantiateType(baseExtendsType, mapper);
|
||||
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper): Type {
|
||||
const checkType = instantiateType(root.checkType, mapper);
|
||||
const extendsType = instantiateType(root.extendsType, mapper);
|
||||
// Return falseType for a definitely false extends check. We check an instantations of the two
|
||||
// types with type parameters mapped to the wildcard type, the most permissive instantiations
|
||||
// possible (the wildcard type is assignable to and from all types). If those are not related,
|
||||
// then no instatiations will be and we can just return the false branch type.
|
||||
if (!typeMaybeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(extendsType))) {
|
||||
return instantiateType(baseFalseType, mapper);
|
||||
return instantiateType(root.falseType, mapper);
|
||||
}
|
||||
// The check could be true for some instantiation
|
||||
let combinedMapper: TypeMapper;
|
||||
if (inferTypeParameters) {
|
||||
const inferences = map(inferTypeParameters, createInferenceInfo);
|
||||
if (root.inferTypeParameters) {
|
||||
const inferences = map(root.inferTypeParameters, createInferenceInfo);
|
||||
// We don't want inferences from constraints as they may cause us to eagerly resolve the
|
||||
// conditional type instead of deferring resolution. Also, we always want strict function
|
||||
// types rules (i.e. proper contravariance) for inferences.
|
||||
inferTypes(inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
|
||||
// We infer 'never' when there are no candidates for a type parameter
|
||||
const inferredTypes = map(inferences, inference => getTypeFromInference(inference) || neverType);
|
||||
const inferenceMapper = createTypeMapper(inferTypeParameters, inferredTypes);
|
||||
combinedMapper = mapper ? combineTypeMappers(mapper, inferenceMapper) : inferenceMapper;
|
||||
// We infer {} when there are no candidates for a type parameter
|
||||
const inferredTypes = map(inferences, inference => getTypeFromInference(inference) || emptyObjectType);
|
||||
combinedMapper = combineTypeMappers(mapper, createTypeMapper(root.inferTypeParameters, inferredTypes));
|
||||
}
|
||||
// Return union of trueType and falseType for any and never since they match anything
|
||||
if (checkType.flags & TypeFlags.Any || (checkType.flags & TypeFlags.Never && !(extendsType.flags & TypeFlags.Never))) {
|
||||
return getUnionType([instantiateType(baseTrueType, combinedMapper || mapper), instantiateType(baseFalseType, mapper)]);
|
||||
// Return union of trueType and falseType for 'any' since it matches anything
|
||||
if (checkType.flags & TypeFlags.Any) {
|
||||
return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
|
||||
}
|
||||
// Instantiate the extends type including inferences for 'infer T' type parameters
|
||||
const inferredExtendsType = combinedMapper ? instantiateType(baseExtendsType, combinedMapper) : extendsType;
|
||||
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
|
||||
// Return trueType for a definitely true extends check. The definitely assignable relation excludes
|
||||
// type variable constraints from consideration. Without the definitely assignable relation, the type
|
||||
// type Foo<T extends { x: any }> = T extends { x: string } ? string : number
|
||||
// would immediately resolve to 'string' instead of being deferred.
|
||||
if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) {
|
||||
return instantiateType(baseTrueType, combinedMapper || mapper);
|
||||
return instantiateType(root.trueType, combinedMapper || mapper);
|
||||
}
|
||||
// Return a deferred type for a check that is neither definitely true nor definitely false
|
||||
const erasedCheckType = getActualTypeParameter(checkType);
|
||||
const trueType = instantiateType(baseTrueType, mapper);
|
||||
const falseType = instantiateType(baseFalseType, mapper);
|
||||
// We compute the cache key from the ids of the four constituent types, plus an indicator of whether the
|
||||
// type is distributive (i.e. whether the original declaration has a type parameter as the check type).
|
||||
const isDistributive = (target ? target.checkType : erasedCheckType).flags & TypeFlags.TypeParameter ? 1 : 0;
|
||||
const id = erasedCheckType.id + "," + extendsType.id + "," + trueType.id + "," + falseType.id + "," + isDistributive;
|
||||
const cached = conditionalTypes.get(id);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const result = createConditionalType(erasedCheckType, extendsType, trueType, falseType,
|
||||
inferTypeParameters, target, mapper, aliasSymbol, instantiateTypes(baseAliasTypeArguments, mapper));
|
||||
conditionalTypes.set(id, result);
|
||||
const result = <ConditionalType>createType(TypeFlags.Conditional);
|
||||
result.root = root;
|
||||
result.checkType = erasedCheckType;
|
||||
result.extendsType = extendsType;
|
||||
result.mapper = mapper;
|
||||
result.aliasSymbol = root.aliasSymbol;
|
||||
result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper);
|
||||
return result;
|
||||
}
|
||||
|
||||
function isDistributiveConditionalType(type: ConditionalType) {
|
||||
return !!((type.target || type).checkType.flags & TypeFlags.TypeParameter);
|
||||
function getTrueTypeFromConditionalType(type: ConditionalType) {
|
||||
return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(type.root.trueType, type.mapper));
|
||||
}
|
||||
|
||||
function getFalseTypeFromConditionalType(type: ConditionalType) {
|
||||
return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
|
||||
}
|
||||
|
||||
function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] {
|
||||
@@ -8294,11 +8276,28 @@ namespace ts {
|
||||
function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getConditionalType(
|
||||
getTypeFromTypeNode(node.checkType), getTypeFromTypeNode(node.extendsType),
|
||||
getTypeFromTypeNode(node.trueType), getTypeFromTypeNode(node.falseType),
|
||||
getInferTypeParameters(node), /*target*/ undefined, /*mapper*/ undefined,
|
||||
getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
|
||||
const checkType = getTypeFromTypeNode(node.checkType);
|
||||
const aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
|
||||
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
|
||||
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node));
|
||||
const root: ConditionalRoot = {
|
||||
node,
|
||||
checkType,
|
||||
extendsType: getTypeFromTypeNode(node.extendsType),
|
||||
trueType: getTypeFromTypeNode(node.trueType),
|
||||
falseType: getTypeFromTypeNode(node.falseType),
|
||||
isDistributive: !!(checkType.flags & TypeFlags.TypeParameter),
|
||||
inferTypeParameters: getInferTypeParameters(node),
|
||||
outerTypeParameters,
|
||||
instantiations: undefined,
|
||||
aliasSymbol: getAliasSymbolForTypeNode(node),
|
||||
aliasTypeArguments
|
||||
};
|
||||
links.resolvedType = getConditionalType(root, /*mapper*/ undefined);
|
||||
if (outerTypeParameters) {
|
||||
root.instantiations = createMap<Type>();
|
||||
root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType);
|
||||
}
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -8689,6 +8688,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
|
||||
if (!mapper1) return mapper2;
|
||||
if (!mapper2) return mapper1;
|
||||
return t => instantiateType(mapper1(t), mapper2);
|
||||
}
|
||||
|
||||
@@ -8886,24 +8887,36 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper): Type {
|
||||
const target = type.target || type;
|
||||
const combinedMapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
|
||||
const root = type.root;
|
||||
if (root.outerTypeParameters) {
|
||||
// We are instantiating a conditional type that has one or more type parameters in scope. Apply the
|
||||
// mapper to the type parameters to produce the effective list of type arguments, and compute the
|
||||
// instantiation cache key from the type IDs of the type arguments.
|
||||
const typeArguments = map(root.outerTypeParameters, mapper);
|
||||
const id = getTypeListId(typeArguments);
|
||||
let result = root.instantiations.get(id);
|
||||
if (!result) {
|
||||
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
|
||||
result = instantiateConditionalType(root, newMapper);
|
||||
root.instantiations.set(id, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function instantiateConditionalType(root: ConditionalRoot, mapper: TypeMapper): Type {
|
||||
// Check if we have a conditional type where the check type is a naked type parameter. If so,
|
||||
// the conditional type is distributive over union types and when T is instantiated to a union
|
||||
// type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y).
|
||||
if (isDistributiveConditionalType(target)) {
|
||||
const checkType = <TypeParameter>target.checkType;
|
||||
const instantiatedType = combinedMapper(checkType);
|
||||
if (checkType !== instantiatedType && instantiatedType.flags & TypeFlags.Union) {
|
||||
return mapType(instantiatedType, t => instantiateConditionalType(target, createReplacementMapper(checkType, t, combinedMapper)));
|
||||
if (root.isDistributive) {
|
||||
const checkType = <TypeParameter>root.checkType;
|
||||
const instantiatedType = mapper(checkType);
|
||||
if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
|
||||
return mapType(instantiatedType, t => getConditionalType(root, createReplacementMapper(checkType, t, mapper)));
|
||||
}
|
||||
}
|
||||
return instantiateConditionalType(target, combinedMapper);
|
||||
}
|
||||
|
||||
function instantiateConditionalType(type: ConditionalType, mapper: TypeMapper): Type {
|
||||
return getConditionalType(instantiateType(type.checkType, mapper), type.extendsType, type.trueType, type.falseType,
|
||||
type.inferTypeParameters, type, mapper, type.aliasSymbol, type.aliasTypeArguments);
|
||||
return getConditionalType(root, mapper);
|
||||
}
|
||||
|
||||
function instantiateType(type: Type, mapper: TypeMapper): Type {
|
||||
@@ -8945,7 +8958,7 @@ namespace ts {
|
||||
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.Conditional) {
|
||||
return getConditionalTypeInstantiation(<ConditionalType>type, mapper);
|
||||
return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));
|
||||
}
|
||||
if (type.flags & TypeFlags.Substitution) {
|
||||
return mapper((<SubstitutionType>type).typeParameter);
|
||||
@@ -9691,11 +9704,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
if (flags & TypeFlags.Conditional) {
|
||||
if (result = isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType, /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType, /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo((<ConditionalType>source).trueType, (<ConditionalType>target).trueType, /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo((<ConditionalType>source).falseType, (<ConditionalType>target).falseType, /*reportErrors*/ false)) {
|
||||
if (isDistributiveConditionalType(<ConditionalType>source) === isDistributiveConditionalType(<ConditionalType>target)) {
|
||||
if ((<ConditionalType>source).root.isDistributive === (<ConditionalType>target).root.isDistributive) {
|
||||
if (result = isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType, /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType, /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), /*reportErrors*/ false)) {
|
||||
if (result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), /*reportErrors*/ false)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -10085,20 +10098,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.Conditional) {
|
||||
if (relation !== definitelyAssignableRelation) {
|
||||
const constraint = getConstraintOfDistributiveConditionalType(<ConditionalType>source);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(constraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target.flags & TypeFlags.Conditional) {
|
||||
if (isTypeIdenticalTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) &&
|
||||
isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType)) {
|
||||
if (result = isRelatedTo((<ConditionalType>source).trueType, (<ConditionalType>target).trueType, reportErrors)) {
|
||||
result &= isRelatedTo((<ConditionalType>source).falseType, (<ConditionalType>target).falseType, reportErrors);
|
||||
if (result = isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
|
||||
result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), reportErrors);
|
||||
}
|
||||
if (result) {
|
||||
errorInfo = saveErrorInfo;
|
||||
@@ -10106,9 +10110,21 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (result = isRelatedTo(getDefaultConstraintOfConditionalType(<ConditionalType>source), target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
else if (relation !== definitelyAssignableRelation) {
|
||||
const distributiveConstraint = getConstraintOfDistributiveConditionalType(<ConditionalType>source);
|
||||
if (distributiveConstraint) {
|
||||
if (result = isRelatedTo(distributiveConstraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
const defaultConstraint = getDefaultConstraintOfConditionalType(<ConditionalType>source);
|
||||
if (defaultConstraint) {
|
||||
if (result = isRelatedTo(defaultConstraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -11479,12 +11495,23 @@ namespace ts {
|
||||
let symbolStack: Symbol[];
|
||||
let visited: Map<boolean>;
|
||||
let contravariant = false;
|
||||
let propagationType: Type;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
function inferFromTypes(source: Type, target: Type) {
|
||||
if (!couldContainTypeVariables(target)) {
|
||||
return;
|
||||
}
|
||||
if (source.flags & (TypeFlags.Any | TypeFlags.Never) && source !== silentNeverType) {
|
||||
// We are inferring from 'any' or 'never'. We want to infer this type for every type parameter
|
||||
// referenced in the target type, so we record the propagation type and infer from the target
|
||||
// to itself. Then, as we find candidates we substitute the propagation type.
|
||||
const savePropagationType = propagationType;
|
||||
propagationType = source;
|
||||
inferFromTypes(target, target);
|
||||
propagationType = savePropagationType;
|
||||
return;
|
||||
}
|
||||
if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) {
|
||||
// Source and target are types originating in the same generic type alias declaration.
|
||||
// Simply infer from source type arguments to target type arguments.
|
||||
@@ -11552,11 +11579,12 @@ namespace ts {
|
||||
inference.priority = priority;
|
||||
}
|
||||
if (priority === inference.priority) {
|
||||
const candidate = propagationType || source;
|
||||
if (contravariant) {
|
||||
inference.contraCandidates = append(inference.contraCandidates, source);
|
||||
inference.contraCandidates = append(inference.contraCandidates, candidate);
|
||||
}
|
||||
else {
|
||||
inference.candidates = append(inference.candidates, source);
|
||||
inference.candidates = append(inference.candidates, candidate);
|
||||
}
|
||||
}
|
||||
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||
@@ -11599,8 +11627,8 @@ namespace ts {
|
||||
else if (source.flags & TypeFlags.Conditional && target.flags & TypeFlags.Conditional) {
|
||||
inferFromTypes((<ConditionalType>source).checkType, (<ConditionalType>target).checkType);
|
||||
inferFromTypes((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType);
|
||||
inferFromTypes((<ConditionalType>source).trueType, (<ConditionalType>target).trueType);
|
||||
inferFromTypes((<ConditionalType>source).falseType, (<ConditionalType>target).falseType);
|
||||
inferFromTypes(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target));
|
||||
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
const targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
@@ -12424,6 +12452,9 @@ namespace ts {
|
||||
// is a union type, the mapping function is applied to each constituent type and a union
|
||||
// of the resulting types is returned.
|
||||
function mapType(type: Type, mapper: (t: Type) => Type, noReductions?: boolean): Type {
|
||||
if (type.flags & TypeFlags.Never) {
|
||||
return type;
|
||||
}
|
||||
if (!(type.flags & TypeFlags.Union)) {
|
||||
return mapper(type);
|
||||
}
|
||||
|
||||
@@ -3821,16 +3821,27 @@ namespace ts {
|
||||
type: InstantiableType | UnionOrIntersectionType;
|
||||
}
|
||||
|
||||
// T extends U ? X : Y (TypeFlags.Conditional)
|
||||
export interface ConditionalType extends InstantiableType {
|
||||
export interface ConditionalRoot {
|
||||
node: ConditionalTypeNode;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
trueType: Type;
|
||||
falseType: Type;
|
||||
/* @internal */
|
||||
isDistributive: boolean;
|
||||
inferTypeParameters: TypeParameter[];
|
||||
/* @internal */
|
||||
target?: ConditionalType;
|
||||
outerTypeParameters?: TypeParameter[];
|
||||
instantiations?: Map<Type>;
|
||||
aliasSymbol: Symbol;
|
||||
aliasTypeArguments: Type[];
|
||||
}
|
||||
|
||||
// T extends U ? X : Y (TypeFlags.Conditional)
|
||||
export interface ConditionalType extends InstantiableType {
|
||||
root: ConditionalRoot;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
resolvedTrueType?: Type;
|
||||
resolvedFalseType?: Type;
|
||||
/* @internal */
|
||||
mapper?: TypeMapper;
|
||||
}
|
||||
|
||||
@@ -2192,11 +2192,25 @@ declare namespace ts {
|
||||
interface IndexType extends InstantiableType {
|
||||
type: InstantiableType | UnionOrIntersectionType;
|
||||
}
|
||||
interface ConditionalType extends InstantiableType {
|
||||
interface ConditionalRoot {
|
||||
node: ConditionalTypeNode;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
trueType: Type;
|
||||
falseType: Type;
|
||||
isDistributive: boolean;
|
||||
inferTypeParameters: TypeParameter[];
|
||||
outerTypeParameters?: TypeParameter[];
|
||||
instantiations?: Map<Type>;
|
||||
aliasSymbol: Symbol;
|
||||
aliasTypeArguments: Type[];
|
||||
}
|
||||
interface ConditionalType extends InstantiableType {
|
||||
root: ConditionalRoot;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
resolvedTrueType?: Type;
|
||||
resolvedFalseType?: Type;
|
||||
}
|
||||
interface SubstitutionType extends InstantiableType {
|
||||
typeParameter: TypeParameter;
|
||||
|
||||
16
tests/baselines/reference/api/typescript.d.ts
vendored
16
tests/baselines/reference/api/typescript.d.ts
vendored
@@ -2192,11 +2192,25 @@ declare namespace ts {
|
||||
interface IndexType extends InstantiableType {
|
||||
type: InstantiableType | UnionOrIntersectionType;
|
||||
}
|
||||
interface ConditionalType extends InstantiableType {
|
||||
interface ConditionalRoot {
|
||||
node: ConditionalTypeNode;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
trueType: Type;
|
||||
falseType: Type;
|
||||
isDistributive: boolean;
|
||||
inferTypeParameters: TypeParameter[];
|
||||
outerTypeParameters?: TypeParameter[];
|
||||
instantiations?: Map<Type>;
|
||||
aliasSymbol: Symbol;
|
||||
aliasTypeArguments: Type[];
|
||||
}
|
||||
interface ConditionalType extends InstantiableType {
|
||||
root: ConditionalRoot;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
resolvedTrueType?: Type;
|
||||
resolvedFalseType?: Type;
|
||||
}
|
||||
interface SubstitutionType extends InstantiableType {
|
||||
typeParameter: TypeParameter;
|
||||
|
||||
@@ -157,7 +157,7 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(275,43): error TS
|
||||
|
||||
type T20 = TypeName<string | (() => void)>; // "string" | "function"
|
||||
type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // never
|
||||
type T23 = TypeName<{}>; // "object"
|
||||
|
||||
type KnockoutObservable<T> = { object: T };
|
||||
@@ -329,7 +329,7 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(275,43): error TS
|
||||
type Q1 = IsString<number>; // false
|
||||
type Q2 = IsString<"abc">; // true
|
||||
type Q3 = IsString<any>; // boolean
|
||||
type Q4 = IsString<never>; // boolean
|
||||
type Q4 = IsString<never>; // never
|
||||
|
||||
type N1 = Not<false>; // true
|
||||
type N2 = Not<true>; // false
|
||||
@@ -357,9 +357,9 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(275,43): error TS
|
||||
|
||||
type T40 = never extends never ? true : false; // true
|
||||
type T41 = number extends never ? true : false; // false
|
||||
type T42 = never extends number ? true : false; // boolean
|
||||
type T42 = never extends number ? true : false; // true
|
||||
|
||||
type IsNever<T> = T extends never ? true : false;
|
||||
type IsNever<T> = [T] extends [never] ? true : false;
|
||||
|
||||
type T50 = IsNever<never>; // true
|
||||
type T51 = IsNever<number>; // false
|
||||
|
||||
@@ -64,7 +64,7 @@ type TypeName<T> =
|
||||
|
||||
type T20 = TypeName<string | (() => void)>; // "string" | "function"
|
||||
type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // never
|
||||
type T23 = TypeName<{}>; // "object"
|
||||
|
||||
type KnockoutObservable<T> = { object: T };
|
||||
@@ -172,7 +172,7 @@ type IsString<T> = Extends<T, string>;
|
||||
type Q1 = IsString<number>; // false
|
||||
type Q2 = IsString<"abc">; // true
|
||||
type Q3 = IsString<any>; // boolean
|
||||
type Q4 = IsString<never>; // boolean
|
||||
type Q4 = IsString<never>; // never
|
||||
|
||||
type N1 = Not<false>; // true
|
||||
type N2 = Not<true>; // false
|
||||
@@ -200,9 +200,9 @@ type O9 = Or<boolean, boolean>; // boolean
|
||||
|
||||
type T40 = never extends never ? true : false; // true
|
||||
type T41 = number extends never ? true : false; // false
|
||||
type T42 = never extends number ? true : false; // boolean
|
||||
type T42 = never extends number ? true : false; // true
|
||||
|
||||
type IsNever<T> = T extends never ? true : false;
|
||||
type IsNever<T> = [T] extends [never] ? true : false;
|
||||
|
||||
type T50 = IsNever<never>; // true
|
||||
type T51 = IsNever<number>; // false
|
||||
@@ -551,7 +551,7 @@ declare type O9 = Or<boolean, boolean>;
|
||||
declare type T40 = never extends never ? true : false;
|
||||
declare type T41 = number extends never ? true : false;
|
||||
declare type T42 = never extends number ? true : false;
|
||||
declare type IsNever<T> = T extends never ? true : false;
|
||||
declare type IsNever<T> = [T] extends [never] ? true : false;
|
||||
declare type T50 = IsNever<never>;
|
||||
declare type T51 = IsNever<number>;
|
||||
declare type T52 = IsNever<any>;
|
||||
@@ -572,7 +572,7 @@ declare type T82 = Eq2<false, true>;
|
||||
declare type T83 = Eq2<false, false>;
|
||||
declare type Foo<T> = T extends string ? boolean : number;
|
||||
declare type Bar<T> = T extends string ? boolean : number;
|
||||
declare const convert: <U>(value: Foo<U>) => Foo<U>;
|
||||
declare const convert: <U>(value: Foo<U>) => Bar<U>;
|
||||
declare type Baz<T> = Foo<T>;
|
||||
declare const convert2: <T>(value: Foo<T>) => Foo<T>;
|
||||
declare function f31<T>(): void;
|
||||
|
||||
@@ -243,7 +243,7 @@ type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "f
|
||||
>T21 : Symbol(T21, Decl(conditionalTypes1.ts, 63, 43))
|
||||
>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 53, 43))
|
||||
|
||||
type T22 = TypeName<never>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // never
|
||||
>T22 : Symbol(T22, Decl(conditionalTypes1.ts, 64, 25))
|
||||
>TypeName : Symbol(TypeName, Decl(conditionalTypes1.ts, 53, 43))
|
||||
|
||||
@@ -668,7 +668,7 @@ type Q3 = IsString<any>; // boolean
|
||||
>Q3 : Symbol(Q3, Decl(conditionalTypes1.ts, 171, 26))
|
||||
>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 166, 63))
|
||||
|
||||
type Q4 = IsString<never>; // boolean
|
||||
type Q4 = IsString<never>; // never
|
||||
>Q4 : Symbol(Q4, Decl(conditionalTypes1.ts, 172, 24))
|
||||
>IsString : Symbol(IsString, Decl(conditionalTypes1.ts, 166, 63))
|
||||
|
||||
@@ -762,16 +762,16 @@ type T40 = never extends never ? true : false; // true
|
||||
type T41 = number extends never ? true : false; // false
|
||||
>T41 : Symbol(T41, Decl(conditionalTypes1.ts, 199, 46))
|
||||
|
||||
type T42 = never extends number ? true : false; // boolean
|
||||
type T42 = never extends number ? true : false; // true
|
||||
>T42 : Symbol(T42, Decl(conditionalTypes1.ts, 200, 47))
|
||||
|
||||
type IsNever<T> = T extends never ? true : false;
|
||||
type IsNever<T> = [T] extends [never] ? true : false;
|
||||
>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 201, 47))
|
||||
>T : Symbol(T, Decl(conditionalTypes1.ts, 203, 13))
|
||||
>T : Symbol(T, Decl(conditionalTypes1.ts, 203, 13))
|
||||
|
||||
type T50 = IsNever<never>; // true
|
||||
>T50 : Symbol(T50, Decl(conditionalTypes1.ts, 203, 49))
|
||||
>T50 : Symbol(T50, Decl(conditionalTypes1.ts, 203, 53))
|
||||
>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 201, 47))
|
||||
|
||||
type T51 = IsNever<number>; // false
|
||||
|
||||
@@ -254,8 +254,8 @@ type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "f
|
||||
>T21 : "string" | "number" | "boolean" | "undefined" | "object" | "function"
|
||||
>TypeName : TypeName<T>
|
||||
|
||||
type T22 = TypeName<never>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
>T22 : "string" | "number" | "boolean" | "undefined" | "object" | "function"
|
||||
type T22 = TypeName<never>; // never
|
||||
>T22 : never
|
||||
>TypeName : TypeName<T>
|
||||
|
||||
type T23 = TypeName<{}>; // "object"
|
||||
@@ -741,8 +741,8 @@ type Q3 = IsString<any>; // boolean
|
||||
>Q3 : boolean
|
||||
>IsString : Extends<T, string>
|
||||
|
||||
type Q4 = IsString<never>; // boolean
|
||||
>Q4 : boolean
|
||||
type Q4 = IsString<never>; // never
|
||||
>Q4 : never
|
||||
>IsString : Extends<T, string>
|
||||
|
||||
type N1 = Not<false>; // true
|
||||
@@ -865,12 +865,12 @@ type T41 = number extends never ? true : false; // false
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
type T42 = never extends number ? true : false; // boolean
|
||||
>T42 : boolean
|
||||
type T42 = never extends number ? true : false; // true
|
||||
>T42 : true
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
type IsNever<T> = T extends never ? true : false;
|
||||
type IsNever<T> = [T] extends [never] ? true : false;
|
||||
>IsNever : IsNever<T>
|
||||
>T : T
|
||||
>T : T
|
||||
@@ -1010,8 +1010,8 @@ type Bar<T> = T extends string ? boolean : number;
|
||||
>T : T
|
||||
|
||||
const convert = <U>(value: Foo<U>): Bar<U> => value;
|
||||
>convert : <U>(value: Foo<U>) => Foo<U>
|
||||
><U>(value: Foo<U>): Bar<U> => value : <U>(value: Foo<U>) => Foo<U>
|
||||
>convert : <U>(value: Foo<U>) => Bar<U>
|
||||
><U>(value: Foo<U>): Bar<U> => value : <U>(value: Foo<U>) => Bar<U>
|
||||
>U : U
|
||||
>value : Foo<U>
|
||||
>Foo : Foo<T>
|
||||
@@ -1095,7 +1095,7 @@ function f33<T, U>() {
|
||||
>U : U
|
||||
|
||||
type T2 = Bar<T & U>;
|
||||
>T2 : Foo<T & U>
|
||||
>T2 : Bar<T & U>
|
||||
>Bar : Bar<T>
|
||||
>T : T
|
||||
>U : U
|
||||
@@ -1106,7 +1106,7 @@ function f33<T, U>() {
|
||||
|
||||
var z: T2;
|
||||
>z : Foo<T & U>
|
||||
>T2 : Foo<T & U>
|
||||
>T2 : Bar<T & U>
|
||||
}
|
||||
|
||||
// Repro from #21823
|
||||
@@ -1236,7 +1236,7 @@ function f50() {
|
||||
>T : T
|
||||
|
||||
type Omit<T extends object> = { [P in keyof T]: If<Eq<T[P], never>, never, P>; }[keyof T];
|
||||
>Omit : { [P in keyof T]: (T[P] extends never ? boolean : false) extends false ? P : never; }[keyof T]
|
||||
>Omit : { [P in keyof T]: (T[P] extends never ? never : false) extends false ? P : never; }[keyof T]
|
||||
>T : T
|
||||
>P : P
|
||||
>T : T
|
||||
@@ -1263,7 +1263,7 @@ function f50() {
|
||||
|
||||
type A = Omit<{ a: void; b: never; }>; // 'a'
|
||||
>A : "a"
|
||||
>Omit : { [P in keyof T]: (T[P] extends never ? boolean : false) extends false ? P : never; }[keyof T]
|
||||
>Omit : { [P in keyof T]: (T[P] extends never ? never : false) extends false ? P : never; }[keyof T]
|
||||
>a : void
|
||||
>b : never
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(134,40): error TS2322:
|
||||
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
|
||||
type T14 = ReturnType<typeof f1>; // { a: number, b: string }
|
||||
type T15 = ReturnType<any>; // any
|
||||
type T16 = ReturnType<never>; // any
|
||||
type T16 = ReturnType<never>; // never
|
||||
type T17 = ReturnType<string>; // Error
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'string' does not satisfy the constraint '(...args: any[]) => any'.
|
||||
@@ -61,7 +61,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(134,40): error TS2322:
|
||||
|
||||
type U10 = InstanceType<typeof C>; // C
|
||||
type U11 = InstanceType<any>; // any
|
||||
type U12 = InstanceType<never>; // any
|
||||
type U12 = InstanceType<never>; // never
|
||||
type U13 = InstanceType<string>; // Error
|
||||
~~~~~~
|
||||
!!! error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any[]) => any'.
|
||||
@@ -72,7 +72,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(134,40): error TS2322:
|
||||
|
||||
type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
|
||||
|
||||
type T20 = ArgumentType<() => void>; // never
|
||||
type T20 = ArgumentType<() => void>; // {}
|
||||
type T21 = ArgumentType<(x: string) => number>; // string
|
||||
type T22 = ArgumentType<(x?: string) => number>; // string | undefined
|
||||
type T23 = ArgumentType<(...args: string[]) => number>; // string
|
||||
@@ -84,7 +84,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(134,40): error TS2322:
|
||||
!!! error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'.
|
||||
!!! error TS2344: Type 'Function' provides no match for the signature '(x: any): any'.
|
||||
type T26 = ArgumentType<any>; // any
|
||||
type T27 = ArgumentType<never>; // any
|
||||
type T27 = ArgumentType<never>; // never
|
||||
|
||||
type X1<T extends { x: any, y: any }> = T extends { x: infer X, y: infer Y } ? [X, Y] : any;
|
||||
|
||||
|
||||
@@ -28,26 +28,26 @@ type T12 = ReturnType<(<T>() => T)>; // {}
|
||||
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
|
||||
type T14 = ReturnType<typeof f1>; // { a: number, b: string }
|
||||
type T15 = ReturnType<any>; // any
|
||||
type T16 = ReturnType<never>; // any
|
||||
type T16 = ReturnType<never>; // never
|
||||
type T17 = ReturnType<string>; // Error
|
||||
type T18 = ReturnType<Function>; // Error
|
||||
|
||||
type U10 = InstanceType<typeof C>; // C
|
||||
type U11 = InstanceType<any>; // any
|
||||
type U12 = InstanceType<never>; // any
|
||||
type U12 = InstanceType<never>; // never
|
||||
type U13 = InstanceType<string>; // Error
|
||||
type U14 = InstanceType<Function>; // Error
|
||||
|
||||
type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
|
||||
|
||||
type T20 = ArgumentType<() => void>; // never
|
||||
type T20 = ArgumentType<() => void>; // {}
|
||||
type T21 = ArgumentType<(x: string) => number>; // string
|
||||
type T22 = ArgumentType<(x?: string) => number>; // string | undefined
|
||||
type T23 = ArgumentType<(...args: string[]) => number>; // string
|
||||
type T24 = ArgumentType<(x: string, y: string) => number>; // Error
|
||||
type T25 = ArgumentType<Function>; // Error
|
||||
type T26 = ArgumentType<any>; // any
|
||||
type T27 = ArgumentType<never>; // any
|
||||
type T27 = ArgumentType<never>; // never
|
||||
|
||||
type X1<T extends { x: any, y: any }> = T extends { x: infer X, y: infer Y } ? [X, Y] : any;
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ type T15 = ReturnType<any>; // any
|
||||
>T15 : Symbol(T15, Decl(inferTypes1.ts, 27, 33))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --))
|
||||
|
||||
type T16 = ReturnType<never>; // any
|
||||
type T16 = ReturnType<never>; // never
|
||||
>T16 : Symbol(T16, Decl(inferTypes1.ts, 28, 27))
|
||||
>ReturnType : Symbol(ReturnType, Decl(lib.d.ts, --, --))
|
||||
|
||||
@@ -128,7 +128,7 @@ type U11 = InstanceType<any>; // any
|
||||
>U11 : Symbol(U11, Decl(inferTypes1.ts, 33, 34))
|
||||
>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --))
|
||||
|
||||
type U12 = InstanceType<never>; // any
|
||||
type U12 = InstanceType<never>; // never
|
||||
>U12 : Symbol(U12, Decl(inferTypes1.ts, 34, 29))
|
||||
>InstanceType : Symbol(InstanceType, Decl(lib.d.ts, --, --))
|
||||
|
||||
@@ -150,7 +150,7 @@ type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A
|
||||
>A : Symbol(A, Decl(inferTypes1.ts, 39, 66))
|
||||
>A : Symbol(A, Decl(inferTypes1.ts, 39, 66))
|
||||
|
||||
type T20 = ArgumentType<() => void>; // never
|
||||
type T20 = ArgumentType<() => void>; // {}
|
||||
>T20 : Symbol(T20, Decl(inferTypes1.ts, 39, 87))
|
||||
>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34))
|
||||
|
||||
@@ -184,7 +184,7 @@ type T26 = ArgumentType<any>; // any
|
||||
>T26 : Symbol(T26, Decl(inferTypes1.ts, 46, 34))
|
||||
>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34))
|
||||
|
||||
type T27 = ArgumentType<never>; // any
|
||||
type T27 = ArgumentType<never>; // never
|
||||
>T27 : Symbol(T27, Decl(inferTypes1.ts, 47, 29))
|
||||
>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 37, 34))
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ type T15 = ReturnType<any>; // any
|
||||
>T15 : any
|
||||
>ReturnType : ReturnType<T>
|
||||
|
||||
type T16 = ReturnType<never>; // any
|
||||
>T16 : any
|
||||
type T16 = ReturnType<never>; // never
|
||||
>T16 : never
|
||||
>ReturnType : ReturnType<T>
|
||||
|
||||
type T17 = ReturnType<string>; // Error
|
||||
@@ -132,8 +132,8 @@ type U11 = InstanceType<any>; // any
|
||||
>U11 : any
|
||||
>InstanceType : InstanceType<T>
|
||||
|
||||
type U12 = InstanceType<never>; // any
|
||||
>U12 : any
|
||||
type U12 = InstanceType<never>; // never
|
||||
>U12 : never
|
||||
>InstanceType : InstanceType<T>
|
||||
|
||||
type U13 = InstanceType<string>; // Error
|
||||
@@ -154,8 +154,8 @@ type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A
|
||||
>A : A
|
||||
>A : A
|
||||
|
||||
type T20 = ArgumentType<() => void>; // never
|
||||
>T20 : never
|
||||
type T20 = ArgumentType<() => void>; // {}
|
||||
>T20 : {}
|
||||
>ArgumentType : ArgumentType<T>
|
||||
|
||||
type T21 = ArgumentType<(x: string) => number>; // string
|
||||
@@ -188,8 +188,8 @@ type T26 = ArgumentType<any>; // any
|
||||
>T26 : any
|
||||
>ArgumentType : ArgumentType<T>
|
||||
|
||||
type T27 = ArgumentType<never>; // any
|
||||
>T27 : any
|
||||
type T27 = ArgumentType<never>; // never
|
||||
>T27 : never
|
||||
>ArgumentType : ArgumentType<T>
|
||||
|
||||
type X1<T extends { x: any, y: any }> = T extends { x: infer X, y: infer Y } ? [X, Y] : any;
|
||||
@@ -312,7 +312,7 @@ type T60 = infer U; // Error
|
||||
>U : U
|
||||
|
||||
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
|
||||
>T61 : never
|
||||
>T61 : {}
|
||||
>T : T
|
||||
>A : A
|
||||
>B : B
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -66,7 +66,7 @@ type TypeName<T> =
|
||||
|
||||
type T20 = TypeName<string | (() => void)>; // "string" | "function"
|
||||
type T21 = TypeName<any>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // "string" | "number" | "boolean" | "undefined" | "function" | "object"
|
||||
type T22 = TypeName<never>; // never
|
||||
type T23 = TypeName<{}>; // "object"
|
||||
|
||||
type KnockoutObservable<T> = { object: T };
|
||||
@@ -174,7 +174,7 @@ type IsString<T> = Extends<T, string>;
|
||||
type Q1 = IsString<number>; // false
|
||||
type Q2 = IsString<"abc">; // true
|
||||
type Q3 = IsString<any>; // boolean
|
||||
type Q4 = IsString<never>; // boolean
|
||||
type Q4 = IsString<never>; // never
|
||||
|
||||
type N1 = Not<false>; // true
|
||||
type N2 = Not<true>; // false
|
||||
@@ -202,9 +202,9 @@ type O9 = Or<boolean, boolean>; // boolean
|
||||
|
||||
type T40 = never extends never ? true : false; // true
|
||||
type T41 = number extends never ? true : false; // false
|
||||
type T42 = never extends number ? true : false; // boolean
|
||||
type T42 = never extends number ? true : false; // true
|
||||
|
||||
type IsNever<T> = T extends never ? true : false;
|
||||
type IsNever<T> = [T] extends [never] ? true : false;
|
||||
|
||||
type T50 = IsNever<never>; // true
|
||||
type T51 = IsNever<number>; // false
|
||||
|
||||
@@ -30,26 +30,26 @@ type T12 = ReturnType<(<T>() => T)>; // {}
|
||||
type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]
|
||||
type T14 = ReturnType<typeof f1>; // { a: number, b: string }
|
||||
type T15 = ReturnType<any>; // any
|
||||
type T16 = ReturnType<never>; // any
|
||||
type T16 = ReturnType<never>; // never
|
||||
type T17 = ReturnType<string>; // Error
|
||||
type T18 = ReturnType<Function>; // Error
|
||||
|
||||
type U10 = InstanceType<typeof C>; // C
|
||||
type U11 = InstanceType<any>; // any
|
||||
type U12 = InstanceType<never>; // any
|
||||
type U12 = InstanceType<never>; // never
|
||||
type U13 = InstanceType<string>; // Error
|
||||
type U14 = InstanceType<Function>; // Error
|
||||
|
||||
type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
|
||||
|
||||
type T20 = ArgumentType<() => void>; // never
|
||||
type T20 = ArgumentType<() => void>; // {}
|
||||
type T21 = ArgumentType<(x: string) => number>; // string
|
||||
type T22 = ArgumentType<(x?: string) => number>; // string | undefined
|
||||
type T23 = ArgumentType<(...args: string[]) => number>; // string
|
||||
type T24 = ArgumentType<(x: string, y: string) => number>; // Error
|
||||
type T25 = ArgumentType<Function>; // Error
|
||||
type T26 = ArgumentType<any>; // any
|
||||
type T27 = ArgumentType<never>; // any
|
||||
type T27 = ArgumentType<never>; // never
|
||||
|
||||
type X1<T extends { x: any, y: any }> = T extends { x: infer X, y: infer Y } ? [X, Y] : any;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user