Adds support for type parameter defaults

This commit is contained in:
Ron Buckton 2017-01-13 22:53:02 -08:00
parent 2711303539
commit 3d3dae089f
13 changed files with 1711 additions and 54 deletions

View file

@ -164,13 +164,13 @@ namespace ts {
// in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes.
anyFunctionType.flags |= TypeFlags.ContainsAnyFunctionType;
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const noConstraintOrDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const circularConstraintOrDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const anySignature = createSignature(undefined, undefined, 0, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, 0, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, 0, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const silentNeverSignature = createSignature(undefined, undefined, 0, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@ -374,7 +374,8 @@ namespace ts {
Type,
ResolvedBaseConstructorType,
DeclaredType,
ResolvedReturnType
ResolvedReturnType,
ResolvedDefault
}
const builtinGlobals = createMap<Symbol>();
@ -2650,6 +2651,13 @@ namespace ts {
writeSpace(writer);
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack);
}
const defaultType = getDefaultOfTypeParameter(tp);
if (defaultType) {
writeSpace(writer);
writePunctuation(writer, SyntaxKind.EqualsToken);
writeSpace(writer);
buildTypeDisplay(defaultType, writer, enclosingDeclaration, flags, symbolStack);
}
}
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
@ -3046,6 +3054,9 @@ namespace ts {
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
return (<Signature>target).resolvedReturnType;
}
if (propertyName === TypeSystemPropertyName.ResolvedDefault) {
return (<TypeVariable>target).resolvedDefault;
}
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
}
@ -3793,7 +3804,7 @@ namespace ts {
function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] {
const typeArgCount = typeArgumentNodes ? typeArgumentNodes.length : 0;
return filter(getSignaturesOfType(type, SignatureKind.Construct),
sig => (sig.typeParameters ? sig.typeParameters.length : 0) === typeArgCount);
sig => typeArgCount >= sig.minTypeArgumentCount && typeArgCount <= (sig.typeParameters ? sig.typeParameters.length : 0));
}
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] {
@ -4000,6 +4011,7 @@ namespace ts {
type.typeParameters = concatenate(outerTypeParameters, localTypeParameters);
type.outerTypeParameters = outerTypeParameters;
type.localTypeParameters = localTypeParameters;
type.minTypeArgumentCount = getMinTypeArgumentCount(localTypeParameters);
(<GenericType>type).instantiations = createMap<TypeReference>();
(<GenericType>type).instantiations[getTypeListId(type.typeParameters)] = <GenericType>type;
(<GenericType>type).target = <GenericType>type;
@ -4043,6 +4055,7 @@ namespace ts {
// Initialize the instantiation cache for generic type aliases. The declared type corresponds to
// an instantiation of the type alias with the type parameters supplied as type arguments.
links.typeParameters = typeParameters;
links.minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
links.instantiations = createMap<Type>();
links.instantiations[getTypeListId(typeParameters)] = type;
}
@ -4351,11 +4364,12 @@ namespace ts {
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
}
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], minTypeArgumentCount: number, thisParameter: Symbol | undefined, parameters: Symbol[],
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature {
const sig = new Signature(checker);
sig.declaration = declaration;
sig.typeParameters = typeParameters;
sig.minTypeArgumentCount = minTypeArgumentCount;
sig.parameters = parameters;
sig.thisParameter = thisParameter;
sig.resolvedReturnType = resolvedReturnType;
@ -4367,7 +4381,7 @@ namespace ts {
}
function cloneSignature(sig: Signature): Signature {
return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, sig.resolvedReturnType,
return createSignature(sig.declaration, sig.typeParameters, sig.minTypeArgumentCount, sig.thisParameter, sig.parameters, sig.resolvedReturnType,
sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes);
}
@ -4375,17 +4389,19 @@ namespace ts {
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)];
return [createSignature(undefined, classType.localTypeParameters, classType.minTypeArgumentCount, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
const typeArgCount = typeArguments ? typeArguments.length : 0;
const result: Signature[] = [];
for (const baseSig of baseSignatures) {
const minTypeArgumentCount = baseSig.minTypeArgumentCount;
const typeParamCount = baseSig.typeParameters ? baseSig.typeParameters.length : 0;
if (typeParamCount === typeArgCount) {
const sig = typeParamCount ? createSignatureInstantiation(baseSig, typeArguments) : cloneSignature(baseSig);
if (typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount) {
const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount)) : cloneSignature(baseSig);
sig.typeParameters = classType.localTypeParameters;
sig.minTypeArgumentCount = classType.minTypeArgumentCount;
sig.resolvedReturnType = classType;
result.push(sig);
}
@ -4759,11 +4775,11 @@ namespace ts {
function getBaseConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
const constraint = getResolvedBaseConstraint(type);
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
return constraint !== noConstraintOrDefaultType && constraint !== circularConstraintOrDefaultType ? constraint : undefined;
}
function hasNonCircularBaseConstraint(type: TypeVariable): boolean {
return getResolvedBaseConstraint(type) !== circularConstraintType;
return getResolvedBaseConstraint(type) !== circularConstraintOrDefaultType;
}
/**
@ -4777,7 +4793,7 @@ namespace ts {
if (!type.resolvedBaseConstraint) {
typeStack = [];
const constraint = getBaseConstraint(type);
type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
type.resolvedBaseConstraint = circular ? circularConstraintOrDefaultType : getTypeWithThisArgument(constraint || noConstraintOrDefaultType, type);
}
return type.resolvedBaseConstraint;
@ -4824,6 +4840,45 @@ namespace ts {
}
}
function getDefaultOfTypeParameter(typeParameter: TypeParameter): Type {
return hasNonCircularDefault(typeParameter) ? getDefaultFromTypeParameter(typeParameter) : undefined;
// const defaultType = getResolvedDefault(typeParameter);
// return defaultType !== noConstraintOrDefaultType && defaultType !== circularConstraintOrDefaultType ? defaultType : undefined;
}
function hasNonCircularDefault(type: TypeParameter) {
return getResolvedDefault(type) !== circularConstraintOrDefaultType;
}
function getResolvedDefault(typeParameter: TypeParameter) {
if (!typeParameter.resolvedDefault) {
if (!pushTypeResolution(typeParameter, TypeSystemPropertyName.ResolvedDefault)) {
return circularConstraintOrDefaultType;
}
const defaultType = getDefaultFromTypeParameter(typeParameter);
const type = defaultType && getResolvedDefaultWorker(defaultType);
if (!popTypeResolution()) {
return typeParameter.resolvedDefault = circularConstraintOrDefaultType;
}
typeParameter.resolvedDefault = type || noConstraintOrDefaultType;
}
return typeParameter.resolvedDefault;
}
function getResolvedDefaultWorker(type: Type): Type {
if (type.flags & TypeFlags.TypeParameter) {
return getResolvedDefault(<TypeParameter>type);
}
if (type.flags & TypeFlags.UnionOrIntersection) {
const types = (<UnionOrIntersectionType>type).types;
const defaultTypes = filter(map(types, getResolvedDefaultWorker), x => x !== circularConstraintOrDefaultType);
return type.flags & TypeFlags.Union && defaultTypes.length === types.length ? getUnionType(defaultTypes) :
type.flags & TypeFlags.Intersection && defaultTypes.length ? getIntersectionType(defaultTypes) :
undefined;
}
return type;
}
/**
* For a type parameter, return the base constraint of the type parameter. For the string, number,
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
@ -5106,6 +5161,53 @@ namespace ts {
}
}
/**
* Gets the minimum number of type arguments needed to satisfy all non-optional type
* parameters.
*/
function getMinTypeArgumentCount(typeParameters: TypeParameter[] | undefined): number {
let minTypeArgumentCount = 0;
if (typeParameters) {
for (let i = 0; i < typeParameters.length; i++) {
if (!getDefaultFromTypeParameter(typeParameters[i])) {
minTypeArgumentCount = i + 1;
}
}
}
return minTypeArgumentCount;
}
function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: TypeParameter[] | undefined, minTypeArgumentCount: number) {
const numTypeArguments = typeArguments ? typeArguments.length : 0;
const numTypeParameters = typeParameters ? typeParameters.length : 0;
if (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters) {
if (numTypeParameters) {
if (!typeArguments) {
typeArguments = [];
}
const mapper: TypeMapper = t => {
for (let i = 0; i < numTypeParameters; i++) {
if (t === typeParameters[i]) {
if (!typeArguments[i]) {
typeArguments[i] = emptyObjectType;
const defaultType = getDefaultOfTypeParameter(typeParameters[i]);
if (defaultType) {
typeArguments[i] = instantiateType(defaultType, mapper);
}
}
return typeArguments[i];
}
}
return t;
};
for (let i = numTypeArguments; i < numTypeParameters; i++) {
typeArguments[i] = instantiateType(typeParameters[i], mapper);
}
}
}
return typeArguments;
}
function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature {
const links = getNodeLinks(declaration);
if (!links.resolvedSignature) {
@ -5172,7 +5274,7 @@ namespace ts {
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
undefined;
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes);
links.resolvedSignature = createSignature(declaration, typeParameters, getMinTypeArgumentCount(typeParameters), thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes);
}
return links.resolvedSignature;
}
@ -5303,6 +5405,7 @@ namespace ts {
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
typeArguments = fillMissingTypeArguments(typeArguments, signature.typeParameters, signature.minTypeArgumentCount);
const instantiations = signature.instantiations || (signature.instantiations = createMap<Signature>());
const id = getTypeListId(typeArguments);
return instantiations[id] || (instantiations[id] = createSignatureInstantiation(signature, typeArguments));
@ -5381,14 +5484,28 @@ namespace ts {
if (!typeParameter.constraint) {
if (typeParameter.target) {
const targetConstraint = getConstraintOfTypeParameter(typeParameter.target);
typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) : noConstraintType;
typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) : noConstraintOrDefaultType;
}
else {
const constraintDeclaration = getConstraintDeclaration(typeParameter);
typeParameter.constraint = constraintDeclaration ? getTypeFromTypeNode(constraintDeclaration) : noConstraintType;
typeParameter.constraint = constraintDeclaration ? getTypeFromTypeNode(constraintDeclaration) : noConstraintOrDefaultType;
}
}
return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint;
return typeParameter.constraint === noConstraintOrDefaultType ? undefined : typeParameter.constraint;
}
function getDefaultFromTypeParameter(typeParameter: TypeParameter): Type | undefined {
if (!typeParameter.default) {
if (typeParameter.target) {
const targetDefault = getDefaultFromTypeParameter(typeParameter.target);
typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintOrDefaultType;
}
else {
const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameter(decl) && decl.default);
typeParameter.default = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintOrDefaultType;
}
}
return typeParameter.default === noConstraintOrDefaultType ? undefined : typeParameter.default;
}
function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol {
@ -5463,14 +5580,22 @@ namespace ts {
const type = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(symbol));
const typeParameters = type.localTypeParameters;
if (typeParameters) {
if (!node.typeArguments || node.typeArguments.length !== typeParameters.length) {
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
const numTypeArguments = node.typeArguments ? node.typeArguments.length : 0;
if (numTypeArguments < type.minTypeArgumentCount || numTypeArguments > typeParameters.length) {
error(node,
type.minTypeArgumentCount === typeParameters.length
? Diagnostics.Generic_type_0_requires_1_type_argument_s
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments,
typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType),
type.minTypeArgumentCount,
typeParameters.length);
return unknownType;
}
// In a type reference, the outer type parameters of the referenced class or interface are automatically
// supplied as type arguments and the type reference only specifies arguments for the local type parameters
// of the class or interface.
return createTypeReference(<GenericType>type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNode)));
const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, type.minTypeArgumentCount));
return createTypeReference(<GenericType>type, typeArguments);
}
if (node.typeArguments) {
error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
@ -5492,10 +5617,17 @@ namespace ts {
// declared type. Instantiations are cached using the type identities of the type arguments as the key.
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
const type = getDeclaredTypeOfSymbol(symbol);
const typeParameters = getSymbolLinks(symbol).typeParameters;
const { typeParameters, minTypeArgumentCount } = getSymbolLinks(symbol);
if (typeParameters) {
if (!node.typeArguments || node.typeArguments.length !== typeParameters.length) {
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, symbolToString(symbol), typeParameters.length);
const numTypeArguments = node.typeArguments ? node.typeArguments.length : 0;
if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) {
error(node,
minTypeArgumentCount === typeParameters.length
? Diagnostics.Generic_type_0_requires_1_type_argument_s
: Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments,
symbolToString(symbol),
minTypeArgumentCount,
typeParameters.length);
return unknownType;
}
const typeArguments = map(node.typeArguments, getTypeFromTypeNode);
@ -5724,6 +5856,7 @@ namespace ts {
type.typeParameters = typeParameters;
type.outerTypeParameters = undefined;
type.localTypeParameters = typeParameters;
type.minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
type.instantiations = createMap<TypeReference>();
type.instantiations[getTypeListId(type.typeParameters)] = <GenericType>type;
type.target = <GenericType>type;
@ -6608,7 +6741,7 @@ namespace ts {
if (signature.typePredicate) {
freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper);
}
const result = createSignature(signature.declaration, freshTypeParameters,
const result = createSignature(signature.declaration, freshTypeParameters, signature.minTypeArgumentCount,
signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper),
instantiateList(signature.parameters, mapper, instantiateSymbol),
instantiateType(signature.resolvedReturnType, mapper),
@ -9004,11 +9137,13 @@ namespace ts {
inferenceSucceeded = !!unionOrSuperType;
}
else {
// Infer the empty object type when no inferences were made. It is important to remember that
// in this case, inference still succeeds, meaning there is no error for not having inference
// candidates. An inference error only occurs when there are *conflicting* candidates, i.e.
// Infer either the default or the empty object type when no inferences were
// made. It is important to remember that in this case, inference still
// succeeds, meaning there is no error for not having inference candidates. An
// inference error only occurs when there are *conflicting* candidates, i.e.
// candidates with no common supertype.
inferredType = emptyObjectType;
const defaultType = getDefaultOfTypeParameter(context.signature.typeParameters[index]);
inferredType = defaultType ? instantiateType(defaultType, getInferenceMapper(context)) : emptyObjectType;
inferenceSucceeded = true;
}
context.inferredTypes[index] = inferredType;
@ -12710,8 +12845,9 @@ namespace ts {
// If the user supplied type arguments, but the number of type arguments does not match
// the declared number of type parameters, the call has an incorrect arity.
const numTypeParameters = signature.typeParameters ? signature.typeParameters.length : 0;
const hasRightNumberOfTypeArgs = !typeArguments ||
(signature.typeParameters && typeArguments.length === signature.typeParameters.length);
(typeArguments.length >= signature.minTypeArgumentCount && typeArguments.length <= numTypeParameters);
if (!hasRightNumberOfTypeArgs) {
return false;
}
@ -12833,7 +12969,7 @@ namespace ts {
const typeParameters = signature.typeParameters;
let typeArgumentsAreAssignable = true;
let mapper: TypeMapper;
for (let i = 0; i < typeParameters.length; i++) {
for (let i = 0; i < typeArgumentNodes.length; i++) {
if (typeArgumentsAreAssignable /* so far */) {
const constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
@ -13405,23 +13541,25 @@ namespace ts {
? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false)
: undefined;
if (typeArguments) {
for (let i = 0; i < typeArguments.length; i++) {
inferenceContext.inferredTypes[i] = getTypeFromTypeNode(typeArguments[i]);
inferenceContext.inferences[i].isFixed = true;
}
}
while (true) {
candidate = originalCandidate;
if (candidate.typeParameters) {
let typeArgumentTypes: Type[];
if (typeArguments) {
typeArgumentTypes = map(typeArguments, getTypeFromTypeNode);
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
}
else {
typeArgumentsAreValid = typeArguments ? checkTypeArguments(candidate, typeArguments, inferenceContext.inferredTypes, /*reportErrors*/ false) : true;
if (typeArgumentsAreValid) {
inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
typeArgumentTypes = inferenceContext.inferredTypes;
}
if (!typeArgumentsAreValid) {
break;
}
candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
candidate = getSignatureInstantiation(candidate, inferenceContext.inferredTypes);
}
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
break;
@ -15394,11 +15532,19 @@ namespace ts {
}
checkSourceElement(node.constraint);
checkSourceElement(node.default);
const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
if (!hasNonCircularBaseConstraint(typeParameter)) {
error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter));
}
getConstraintOfTypeParameter(getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)));
if (!hasNonCircularDefault(typeParameter)) {
error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter));
}
const constraintType = getConstraintOfTypeParameter(typeParameter);
const defaultType = getDefaultOfTypeParameter(typeParameter);
if (constraintType && defaultType) {
checkTypeAssignableTo(defaultType, getTypeWithThisArgument(constraintType, defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
if (produceDiagnostics) {
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
}
@ -15948,7 +16094,7 @@ namespace ts {
checkDecorators(node);
}
function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArgumentNodes: TypeNode[]): boolean {
function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArgumentNodes: TypeNode[], minTypeArgumentCount: number): boolean {
let typeArguments: Type[];
let mapper: TypeMapper;
let result = true;
@ -15956,7 +16102,7 @@ namespace ts {
const constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
if (!typeArguments) {
typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount);
mapper = createTypeMapper(typeParameters, typeArguments);
}
const typeArgument = typeArguments[i];
@ -15980,7 +16126,8 @@ namespace ts {
if (produceDiagnostics) {
const symbol = getNodeLinks(node).resolvedSymbol;
const typeParameters = symbol.flags & SymbolFlags.TypeAlias ? getSymbolLinks(symbol).typeParameters : (<TypeReference>type).target.localTypeParameters;
checkTypeArgumentConstraints(typeParameters, node.typeArguments);
const minTypeArgumentCount = symbol.flags & SymbolFlags.TypeAlias ? getSymbolLinks(symbol).minTypeArgumentCount : (<TypeReference>type).target.minTypeArgumentCount;
checkTypeArgumentConstraints(typeParameters, node.typeArguments, minTypeArgumentCount);
}
}
if (type.flags & TypeFlags.Enum && !(<EnumType>type).memberTypes && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) {
@ -18182,14 +18329,23 @@ namespace ts {
}
}
/** Check each type parameter and check that type parameters have no duplicate type parameter declarations */
/**
* Check each type parameter and check that type parameters have no duplicate type parameter declarations
*/
function checkTypeParameters(typeParameterDeclarations: TypeParameterDeclaration[]) {
if (typeParameterDeclarations) {
let seenDefault = false;
for (let i = 0; i < typeParameterDeclarations.length; i++) {
const node = typeParameterDeclarations[i];
checkTypeParameter(node);
if (produceDiagnostics) {
if (node.default) {
seenDefault = true;
}
else if (seenDefault) {
error(node, Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters);
}
for (let j = 0; j < i; j++) {
if (typeParameterDeclarations[j].symbol === node.symbol) {
error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
@ -18273,7 +18429,7 @@ namespace ts {
if (baseTypeNode.typeArguments) {
forEach(baseTypeNode.typeArguments, checkSourceElement);
for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments)) {
if (!checkTypeArgumentConstraints(constructor.typeParameters, baseTypeNode.typeArguments)) {
if (!checkTypeArgumentConstraints(constructor.typeParameters, baseTypeNode.typeArguments, constructor.minTypeArgumentCount)) {
break;
}
}
@ -18472,14 +18628,15 @@ namespace ts {
if (tp1.name.text !== tp2.name.text) {
return false;
}
if (!tp1.constraint && !tp2.constraint) {
continue;
if (tp1.constraint || tp2.constraint) {
if (!tp1.constraint || !tp2.constraint || !isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
return false;
}
}
if (!tp1.constraint || !tp2.constraint) {
return false;
}
if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
return false;
if (tp1.default || tp2.default) {
if (!tp1.default || !tp2.default || !isTypeIdenticalTo(getTypeFromTypeNode(tp1.default), getTypeFromTypeNode(tp2.default))) {
return false;
}
}
}
return true;

View file

@ -1000,6 +1000,23 @@ namespace ts {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
}
}
if (node.default && !isPrivateMethodTypeParameter(node)) {
write(" = ");
if (node.parent.kind === SyntaxKind.FunctionType ||
node.parent.kind === SyntaxKind.ConstructorType ||
(node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) {
Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration ||
node.parent.kind === SyntaxKind.MethodSignature ||
node.parent.kind === SyntaxKind.FunctionType ||
node.parent.kind === SyntaxKind.ConstructorType ||
node.parent.kind === SyntaxKind.CallSignature ||
node.parent.kind === SyntaxKind.ConstructSignature);
emitType(node.default);
}
else {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.default, getTypeParameterConstraintVisibilityError);
}
}
function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic {
// Type parameter constraints are named by user so we should always be able to name it

View file

@ -2035,6 +2035,18 @@
"category": "Error",
"code": 2704
},
"Required type parameters may not follow optional type parameters": {
"category": "Error",
"code": 2705
},
"Type parameter '{0}' has a circular default.": {
"category": "Error",
"code": 2706
},
"Generic type '{0}' requires between {1} and {2} type arguments": {
"category": "Error",
"code": 2707
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View file

@ -66,6 +66,7 @@ namespace ts {
case SyntaxKind.TypeParameter:
return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
case SyntaxKind.ShorthandPropertyAssignment:
return visitNodes(cbNodes, node.decorators) ||
@ -2098,6 +2099,10 @@ namespace ts {
}
}
if (parseOptional(SyntaxKind.EqualsToken)) {
node.default = parseType();
}
return finishNode(node);
}

View file

@ -604,6 +604,7 @@ namespace ts {
kind: SyntaxKind.TypeParameter;
name: Identifier;
constraint?: TypeNode;
default?: TypeNode;
// For error recovery purposes.
expression?: Expression;
@ -2679,6 +2680,7 @@ namespace ts {
type?: Type; // Type of value symbol
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
minTypeArgumentCount?: number;
inferredClassType?: Type; // Type of an inferred ES5 class
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
mapper?: TypeMapper; // Type mapper for instantiation alias
@ -2880,6 +2882,8 @@ namespace ts {
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none)
localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none)
/* @internal */
minTypeArgumentCount: number;
thisType: TypeParameter; // The "this" type (undefined if none)
/* @internal */
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
@ -2986,18 +2990,23 @@ namespace ts {
/* @internal */
resolvedBaseConstraint: Type;
/* @internal */
resolvedDefault: Type;
/* @internal */
resolvedIndexType: IndexType;
}
// Type parameters (TypeFlags.TypeParameter)
export interface TypeParameter extends TypeVariable {
constraint: Type; // Constraint
default?: Type;
/* @internal */
target?: TypeParameter; // Instantiation target
/* @internal */
mapper?: TypeMapper; // Instantiation mapper
/* @internal */
isThisType?: boolean;
/* @internal */
resolvedDefaultType?: Type;
}
// Indexed access types (TypeFlags.IndexedAccess)
@ -3021,6 +3030,8 @@ namespace ts {
export interface Signature {
declaration: SignatureDeclaration; // Originating declaration
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
/* @internal */
minTypeArgumentCount: number; // Number of non-optional type parameters
parameters: Symbol[]; // Parameters
/* @internal */
thisParameter?: Symbol; // symbol of this-type parameter

View file

@ -396,6 +396,7 @@ namespace ts {
parameters: Symbol[];
thisParameter: Symbol;
resolvedReturnType: Type;
minTypeArgumentCount: number;
minArgumentCount: number;
hasRestParameter: boolean;
hasLiteralTypes: boolean;

View file

@ -0,0 +1,238 @@
//// [genericDefaults.ts]
declare const x: any;
declare function f00<T = number>(a?: T): T;
const f00c00 = f00();
const f00c01 = f00(1);
const f00c02 = f00("a");
const f00c03 = f00<number>();
const f00c04 = f00<number>(1);
const f00c05 = f00<string>("a");
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
const f01c00 = f01();
const f01c01 = f01(1);
const f01c02 = f01(1, "a");
const f01c03 = f01<number>();
const f01c04 = f01<number>(1);
const f01c05 = f01<number>(1, "a");
const f01c06 = f01<number, string>();
const f01c07 = f01<number, string>(1);
const f01c08 = f01<number, string>(1, "a");
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
const f02c00 = f02();
const f02c01 = f02(1);
const f02c02 = f02(1, "a");
const f02c03 = f02<number>();
const f02c04 = f02<number>(1);
const f02c05 = f02<number>(1, "a");
const f02c06 = f02<number, string>();
const f02c07 = f02<number, string>(1);
const f02c08 = f02<number, string>(1, "a");
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
const f03c00 = f03();
const f03c01 = f03(1);
const f03c02 = f03(1, 1);
const f03c03 = f03<number>();
const f03c04 = f03<number>(1);
const f03c05 = f03<number>(1, 2);
const f03c06 = f03<number, number>();
const f03c07 = f03<number, number>(1);
const f03c08 = f03<number, number>(1, 2);
interface i00<T = number> { a: T; }
const i00c00 = (<i00>x).a;
const i00c01 = (<i00<number>>x).a;
interface i01<T, U = T> { a: [T, U]; }
const i01c00 = (<i01<number>>x).a;
const i01c01 = (<i01<number, string>>x).a;
interface i02<T extends number, U = T> { a: [T, U]; }
const i02c00 = (<i02<number>>x).a;
const i02c01 = (<i02<1>>x).a;
const i02c02 = (<i02<number, number>>x).a;
const i02c03 = (<i02<1, number>>x).a;
const i02c04 = (<i02<number, 1>>x).a;
interface i03<T extends number, U extends T = T> { a: [T, U]; }
const i03c00 = (<i03<number>>x).a;
const i03c01 = (<i03<1>>x).a;
const i03c02 = (<i03<number, number>>x).a;
const i03c03 = (<i03<1, 1>>x).a;
const i03c04 = (<i03<number, 1>>x).a;
interface Base01<T> { a: T; }
interface Base01Constructor { new <T = number>(a?: T): Base01<T>; }
declare const Base01: Base01Constructor;
const Base01c00 = new Base01();
const Base01c01 = new Base01(1);
const Base01c02 = new Base01<number>();
const Base01c03 = new Base01<number>(1);
declare class Derived01<T> extends Base01<T> { }
const Derived01c00 = new Derived01();
const Derived01c01 = new Derived01(1);
const Derived01c02 = new Derived01<number>();
const Derived01c03 = new Derived01<number>(1);
declare class Derived02<T = string> extends Base01<T> { }
const Derived02c00 = new Derived02();
const Derived02c01 = new Derived02(1);
const Derived02c02 = new Derived02<number>();
const Derived02c03 = new Derived02<number>(1);
//// [genericDefaults.js]
var f00c00 = f00();
var f00c01 = f00(1);
var f00c02 = f00("a");
var f00c03 = f00();
var f00c04 = f00(1);
var f00c05 = f00("a");
var f01c00 = f01();
var f01c01 = f01(1);
var f01c02 = f01(1, "a");
var f01c03 = f01();
var f01c04 = f01(1);
var f01c05 = f01(1, "a");
var f01c06 = f01();
var f01c07 = f01(1);
var f01c08 = f01(1, "a");
var f02c00 = f02();
var f02c01 = f02(1);
var f02c02 = f02(1, "a");
var f02c03 = f02();
var f02c04 = f02(1);
var f02c05 = f02(1, "a");
var f02c06 = f02();
var f02c07 = f02(1);
var f02c08 = f02(1, "a");
var f03c00 = f03();
var f03c01 = f03(1);
var f03c02 = f03(1, 1);
var f03c03 = f03();
var f03c04 = f03(1);
var f03c05 = f03(1, 2);
var f03c06 = f03();
var f03c07 = f03(1);
var f03c08 = f03(1, 2);
var i00c00 = x.a;
var i00c01 = x.a;
var i01c00 = x.a;
var i01c01 = x.a;
var i02c00 = x.a;
var i02c01 = x.a;
var i02c02 = x.a;
var i02c03 = x.a;
var i02c04 = x.a;
var i03c00 = x.a;
var i03c01 = x.a;
var i03c02 = x.a;
var i03c03 = x.a;
var i03c04 = x.a;
var Base01c00 = new Base01();
var Base01c01 = new Base01(1);
var Base01c02 = new Base01();
var Base01c03 = new Base01(1);
var Derived01c00 = new Derived01();
var Derived01c01 = new Derived01(1);
var Derived01c02 = new Derived01();
var Derived01c03 = new Derived01(1);
var Derived02c00 = new Derived02();
var Derived02c01 = new Derived02(1);
var Derived02c02 = new Derived02();
var Derived02c03 = new Derived02(1);
//// [genericDefaults.d.ts]
declare const x: any;
declare function f00<T = number>(a?: T): T;
declare const f00c00: number;
declare const f00c01 = 1;
declare const f00c02 = "a";
declare const f00c03: number;
declare const f00c04: number;
declare const f00c05: string;
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
declare const f01c00: [{}, {}];
declare const f01c01: [number, number];
declare const f01c02: [number, string];
declare const f01c03: [number, number];
declare const f01c04: [number, number];
declare const f01c05: [number, string];
declare const f01c06: [number, string];
declare const f01c07: [number, string];
declare const f01c08: [number, string];
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
declare const f02c00: [number, number];
declare const f02c01: [1, 1];
declare const f02c02: [1, string];
declare const f02c03: [number, number];
declare const f02c04: [number, number];
declare const f02c05: [number, string];
declare const f02c06: [number, string];
declare const f02c07: [number, string];
declare const f02c08: [number, string];
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
declare const f03c00: [number, number];
declare const f03c01: [1, 1];
declare const f03c02: [1, 1];
declare const f03c03: [number, number];
declare const f03c04: [number, number];
declare const f03c05: [number, number];
declare const f03c06: [number, number];
declare const f03c07: [number, number];
declare const f03c08: [number, number];
interface i00<T = number> {
a: T;
}
declare const i00c00: number;
declare const i00c01: number;
interface i01<T, U = T> {
a: [T, U];
}
declare const i01c00: [number, number];
declare const i01c01: [number, string];
interface i02<T extends number, U = T> {
a: [T, U];
}
declare const i02c00: [number, number];
declare const i02c01: [1, 1];
declare const i02c02: [number, number];
declare const i02c03: [1, number];
declare const i02c04: [number, 1];
interface i03<T extends number, U extends T = T> {
a: [T, U];
}
declare const i03c00: [number, number];
declare const i03c01: [1, 1];
declare const i03c02: [number, number];
declare const i03c03: [1, 1];
declare const i03c04: [number, 1];
interface Base01<T> {
a: T;
}
interface Base01Constructor {
new <T = number>(a?: T): Base01<T>;
}
declare const Base01: Base01Constructor;
declare const Base01c00: Base01<number>;
declare const Base01c01: Base01<number>;
declare const Base01c02: Base01<number>;
declare const Base01c03: Base01<number>;
declare class Derived01<T> extends Base01<T> {
}
declare const Derived01c00: Derived01<{}>;
declare const Derived01c01: Derived01<number>;
declare const Derived01c02: Derived01<number>;
declare const Derived01c03: Derived01<number>;
declare class Derived02<T = string> extends Base01<T> {
}
declare const Derived02c00: Derived02<string>;
declare const Derived02c01: Derived02<number>;
declare const Derived02c02: Derived02<number>;
declare const Derived02c03: Derived02<number>;

View file

@ -0,0 +1,390 @@
=== tests/cases/compiler/genericDefaults.ts ===
declare const x: any;
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
declare function f00<T = number>(a?: T): T;
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
>T : Symbol(T, Decl(genericDefaults.ts, 2, 21))
>a : Symbol(a, Decl(genericDefaults.ts, 2, 33))
>T : Symbol(T, Decl(genericDefaults.ts, 2, 21))
>T : Symbol(T, Decl(genericDefaults.ts, 2, 21))
const f00c00 = f00();
>f00c00 : Symbol(f00c00, Decl(genericDefaults.ts, 3, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
const f00c01 = f00(1);
>f00c01 : Symbol(f00c01, Decl(genericDefaults.ts, 4, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
const f00c02 = f00("a");
>f00c02 : Symbol(f00c02, Decl(genericDefaults.ts, 5, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
const f00c03 = f00<number>();
>f00c03 : Symbol(f00c03, Decl(genericDefaults.ts, 6, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
const f00c04 = f00<number>(1);
>f00c04 : Symbol(f00c04, Decl(genericDefaults.ts, 7, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
const f00c05 = f00<string>("a");
>f00c05 : Symbol(f00c05, Decl(genericDefaults.ts, 8, 5))
>f00 : Symbol(f00, Decl(genericDefaults.ts, 0, 21))
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
>T : Symbol(T, Decl(genericDefaults.ts, 10, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 10, 23))
>T : Symbol(T, Decl(genericDefaults.ts, 10, 21))
>a : Symbol(a, Decl(genericDefaults.ts, 10, 31))
>T : Symbol(T, Decl(genericDefaults.ts, 10, 21))
>b : Symbol(b, Decl(genericDefaults.ts, 10, 37))
>U : Symbol(U, Decl(genericDefaults.ts, 10, 23))
>T : Symbol(T, Decl(genericDefaults.ts, 10, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 10, 23))
const f01c00 = f01();
>f01c00 : Symbol(f01c00, Decl(genericDefaults.ts, 11, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c01 = f01(1);
>f01c01 : Symbol(f01c01, Decl(genericDefaults.ts, 12, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c02 = f01(1, "a");
>f01c02 : Symbol(f01c02, Decl(genericDefaults.ts, 13, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c03 = f01<number>();
>f01c03 : Symbol(f01c03, Decl(genericDefaults.ts, 14, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c04 = f01<number>(1);
>f01c04 : Symbol(f01c04, Decl(genericDefaults.ts, 15, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c05 = f01<number>(1, "a");
>f01c05 : Symbol(f01c05, Decl(genericDefaults.ts, 16, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c06 = f01<number, string>();
>f01c06 : Symbol(f01c06, Decl(genericDefaults.ts, 17, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c07 = f01<number, string>(1);
>f01c07 : Symbol(f01c07, Decl(genericDefaults.ts, 18, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
const f01c08 = f01<number, string>(1, "a");
>f01c08 : Symbol(f01c08, Decl(genericDefaults.ts, 19, 5))
>f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32))
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
>T : Symbol(T, Decl(genericDefaults.ts, 21, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 21, 38))
>T : Symbol(T, Decl(genericDefaults.ts, 21, 21))
>a : Symbol(a, Decl(genericDefaults.ts, 21, 46))
>T : Symbol(T, Decl(genericDefaults.ts, 21, 21))
>b : Symbol(b, Decl(genericDefaults.ts, 21, 52))
>U : Symbol(U, Decl(genericDefaults.ts, 21, 38))
>T : Symbol(T, Decl(genericDefaults.ts, 21, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 21, 38))
const f02c00 = f02();
>f02c00 : Symbol(f02c00, Decl(genericDefaults.ts, 22, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c01 = f02(1);
>f02c01 : Symbol(f02c01, Decl(genericDefaults.ts, 23, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c02 = f02(1, "a");
>f02c02 : Symbol(f02c02, Decl(genericDefaults.ts, 24, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c03 = f02<number>();
>f02c03 : Symbol(f02c03, Decl(genericDefaults.ts, 25, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c04 = f02<number>(1);
>f02c04 : Symbol(f02c04, Decl(genericDefaults.ts, 26, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c05 = f02<number>(1, "a");
>f02c05 : Symbol(f02c05, Decl(genericDefaults.ts, 27, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c06 = f02<number, string>();
>f02c06 : Symbol(f02c06, Decl(genericDefaults.ts, 28, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c07 = f02<number, string>(1);
>f02c07 : Symbol(f02c07, Decl(genericDefaults.ts, 29, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
const f02c08 = f02<number, string>(1, "a");
>f02c08 : Symbol(f02c08, Decl(genericDefaults.ts, 30, 5))
>f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43))
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
>T : Symbol(T, Decl(genericDefaults.ts, 32, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 32, 38))
>T : Symbol(T, Decl(genericDefaults.ts, 32, 21))
>T : Symbol(T, Decl(genericDefaults.ts, 32, 21))
>a : Symbol(a, Decl(genericDefaults.ts, 32, 56))
>T : Symbol(T, Decl(genericDefaults.ts, 32, 21))
>b : Symbol(b, Decl(genericDefaults.ts, 32, 62))
>U : Symbol(U, Decl(genericDefaults.ts, 32, 38))
>T : Symbol(T, Decl(genericDefaults.ts, 32, 21))
>U : Symbol(U, Decl(genericDefaults.ts, 32, 38))
const f03c00 = f03();
>f03c00 : Symbol(f03c00, Decl(genericDefaults.ts, 33, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c01 = f03(1);
>f03c01 : Symbol(f03c01, Decl(genericDefaults.ts, 34, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c02 = f03(1, 1);
>f03c02 : Symbol(f03c02, Decl(genericDefaults.ts, 35, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c03 = f03<number>();
>f03c03 : Symbol(f03c03, Decl(genericDefaults.ts, 36, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c04 = f03<number>(1);
>f03c04 : Symbol(f03c04, Decl(genericDefaults.ts, 37, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c05 = f03<number>(1, 2);
>f03c05 : Symbol(f03c05, Decl(genericDefaults.ts, 38, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c06 = f03<number, number>();
>f03c06 : Symbol(f03c06, Decl(genericDefaults.ts, 39, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c07 = f03<number, number>(1);
>f03c07 : Symbol(f03c07, Decl(genericDefaults.ts, 40, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
const f03c08 = f03<number, number>(1, 2);
>f03c08 : Symbol(f03c08, Decl(genericDefaults.ts, 41, 5))
>f03 : Symbol(f03, Decl(genericDefaults.ts, 30, 43))
interface i00<T = number> { a: T; }
>i00 : Symbol(i00, Decl(genericDefaults.ts, 41, 41))
>T : Symbol(T, Decl(genericDefaults.ts, 43, 14))
>a : Symbol(i00.a, Decl(genericDefaults.ts, 43, 27))
>T : Symbol(T, Decl(genericDefaults.ts, 43, 14))
const i00c00 = (<i00>x).a;
>i00c00 : Symbol(i00c00, Decl(genericDefaults.ts, 44, 5))
>(<i00>x).a : Symbol(i00.a, Decl(genericDefaults.ts, 43, 27))
>i00 : Symbol(i00, Decl(genericDefaults.ts, 41, 41))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i00.a, Decl(genericDefaults.ts, 43, 27))
const i00c01 = (<i00<number>>x).a;
>i00c01 : Symbol(i00c01, Decl(genericDefaults.ts, 45, 5))
>(<i00<number>>x).a : Symbol(i00.a, Decl(genericDefaults.ts, 43, 27))
>i00 : Symbol(i00, Decl(genericDefaults.ts, 41, 41))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i00.a, Decl(genericDefaults.ts, 43, 27))
interface i01<T, U = T> { a: [T, U]; }
>i01 : Symbol(i01, Decl(genericDefaults.ts, 45, 34))
>T : Symbol(T, Decl(genericDefaults.ts, 47, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 47, 16))
>T : Symbol(T, Decl(genericDefaults.ts, 47, 14))
>a : Symbol(i01.a, Decl(genericDefaults.ts, 47, 25))
>T : Symbol(T, Decl(genericDefaults.ts, 47, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 47, 16))
const i01c00 = (<i01<number>>x).a;
>i01c00 : Symbol(i01c00, Decl(genericDefaults.ts, 48, 5))
>(<i01<number>>x).a : Symbol(i01.a, Decl(genericDefaults.ts, 47, 25))
>i01 : Symbol(i01, Decl(genericDefaults.ts, 45, 34))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i01.a, Decl(genericDefaults.ts, 47, 25))
const i01c01 = (<i01<number, string>>x).a;
>i01c01 : Symbol(i01c01, Decl(genericDefaults.ts, 49, 5))
>(<i01<number, string>>x).a : Symbol(i01.a, Decl(genericDefaults.ts, 47, 25))
>i01 : Symbol(i01, Decl(genericDefaults.ts, 45, 34))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i01.a, Decl(genericDefaults.ts, 47, 25))
interface i02<T extends number, U = T> { a: [T, U]; }
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>T : Symbol(T, Decl(genericDefaults.ts, 51, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 51, 31))
>T : Symbol(T, Decl(genericDefaults.ts, 51, 14))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>T : Symbol(T, Decl(genericDefaults.ts, 51, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 51, 31))
const i02c00 = (<i02<number>>x).a;
>i02c00 : Symbol(i02c00, Decl(genericDefaults.ts, 52, 5))
>(<i02<number>>x).a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
const i02c01 = (<i02<1>>x).a;
>i02c01 : Symbol(i02c01, Decl(genericDefaults.ts, 53, 5))
>(<i02<1>>x).a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
const i02c02 = (<i02<number, number>>x).a;
>i02c02 : Symbol(i02c02, Decl(genericDefaults.ts, 54, 5))
>(<i02<number, number>>x).a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
const i02c03 = (<i02<1, number>>x).a;
>i02c03 : Symbol(i02c03, Decl(genericDefaults.ts, 55, 5))
>(<i02<1, number>>x).a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
const i02c04 = (<i02<number, 1>>x).a;
>i02c04 : Symbol(i02c04, Decl(genericDefaults.ts, 56, 5))
>(<i02<number, 1>>x).a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
>i02 : Symbol(i02, Decl(genericDefaults.ts, 49, 42))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i02.a, Decl(genericDefaults.ts, 51, 40))
interface i03<T extends number, U extends T = T> { a: [T, U]; }
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>T : Symbol(T, Decl(genericDefaults.ts, 58, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 58, 31))
>T : Symbol(T, Decl(genericDefaults.ts, 58, 14))
>T : Symbol(T, Decl(genericDefaults.ts, 58, 14))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>T : Symbol(T, Decl(genericDefaults.ts, 58, 14))
>U : Symbol(U, Decl(genericDefaults.ts, 58, 31))
const i03c00 = (<i03<number>>x).a;
>i03c00 : Symbol(i03c00, Decl(genericDefaults.ts, 59, 5))
>(<i03<number>>x).a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
const i03c01 = (<i03<1>>x).a;
>i03c01 : Symbol(i03c01, Decl(genericDefaults.ts, 60, 5))
>(<i03<1>>x).a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
const i03c02 = (<i03<number, number>>x).a;
>i03c02 : Symbol(i03c02, Decl(genericDefaults.ts, 61, 5))
>(<i03<number, number>>x).a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
const i03c03 = (<i03<1, 1>>x).a;
>i03c03 : Symbol(i03c03, Decl(genericDefaults.ts, 62, 5))
>(<i03<1, 1>>x).a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
const i03c04 = (<i03<number, 1>>x).a;
>i03c04 : Symbol(i03c04, Decl(genericDefaults.ts, 63, 5))
>(<i03<number, 1>>x).a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
>i03 : Symbol(i03, Decl(genericDefaults.ts, 56, 37))
>x : Symbol(x, Decl(genericDefaults.ts, 0, 13))
>a : Symbol(i03.a, Decl(genericDefaults.ts, 58, 50))
interface Base01<T> { a: T; }
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
>T : Symbol(T, Decl(genericDefaults.ts, 65, 17))
>a : Symbol(Base01.a, Decl(genericDefaults.ts, 65, 21))
>T : Symbol(T, Decl(genericDefaults.ts, 65, 17))
interface Base01Constructor { new <T = number>(a?: T): Base01<T>; }
>Base01Constructor : Symbol(Base01Constructor, Decl(genericDefaults.ts, 65, 29))
>T : Symbol(T, Decl(genericDefaults.ts, 66, 35))
>a : Symbol(a, Decl(genericDefaults.ts, 66, 47))
>T : Symbol(T, Decl(genericDefaults.ts, 66, 35))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
>T : Symbol(T, Decl(genericDefaults.ts, 66, 35))
declare const Base01: Base01Constructor;
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
>Base01Constructor : Symbol(Base01Constructor, Decl(genericDefaults.ts, 65, 29))
const Base01c00 = new Base01();
>Base01c00 : Symbol(Base01c00, Decl(genericDefaults.ts, 69, 5))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
const Base01c01 = new Base01(1);
>Base01c01 : Symbol(Base01c01, Decl(genericDefaults.ts, 70, 5))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
const Base01c02 = new Base01<number>();
>Base01c02 : Symbol(Base01c02, Decl(genericDefaults.ts, 71, 5))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
const Base01c03 = new Base01<number>(1);
>Base01c03 : Symbol(Base01c03, Decl(genericDefaults.ts, 72, 5))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
declare class Derived01<T> extends Base01<T> { }
>Derived01 : Symbol(Derived01, Decl(genericDefaults.ts, 72, 40))
>T : Symbol(T, Decl(genericDefaults.ts, 74, 24))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
>T : Symbol(T, Decl(genericDefaults.ts, 74, 24))
const Derived01c00 = new Derived01();
>Derived01c00 : Symbol(Derived01c00, Decl(genericDefaults.ts, 75, 5))
>Derived01 : Symbol(Derived01, Decl(genericDefaults.ts, 72, 40))
const Derived01c01 = new Derived01(1);
>Derived01c01 : Symbol(Derived01c01, Decl(genericDefaults.ts, 76, 5))
>Derived01 : Symbol(Derived01, Decl(genericDefaults.ts, 72, 40))
const Derived01c02 = new Derived01<number>();
>Derived01c02 : Symbol(Derived01c02, Decl(genericDefaults.ts, 77, 5))
>Derived01 : Symbol(Derived01, Decl(genericDefaults.ts, 72, 40))
const Derived01c03 = new Derived01<number>(1);
>Derived01c03 : Symbol(Derived01c03, Decl(genericDefaults.ts, 78, 5))
>Derived01 : Symbol(Derived01, Decl(genericDefaults.ts, 72, 40))
declare class Derived02<T = string> extends Base01<T> { }
>Derived02 : Symbol(Derived02, Decl(genericDefaults.ts, 78, 46))
>T : Symbol(T, Decl(genericDefaults.ts, 80, 24))
>Base01 : Symbol(Base01, Decl(genericDefaults.ts, 63, 37), Decl(genericDefaults.ts, 68, 13))
>T : Symbol(T, Decl(genericDefaults.ts, 80, 24))
const Derived02c00 = new Derived02();
>Derived02c00 : Symbol(Derived02c00, Decl(genericDefaults.ts, 81, 5))
>Derived02 : Symbol(Derived02, Decl(genericDefaults.ts, 78, 46))
const Derived02c01 = new Derived02(1);
>Derived02c01 : Symbol(Derived02c01, Decl(genericDefaults.ts, 82, 5))
>Derived02 : Symbol(Derived02, Decl(genericDefaults.ts, 78, 46))
const Derived02c02 = new Derived02<number>();
>Derived02c02 : Symbol(Derived02c02, Decl(genericDefaults.ts, 83, 5))
>Derived02 : Symbol(Derived02, Decl(genericDefaults.ts, 78, 46))
const Derived02c03 = new Derived02<number>(1);
>Derived02c03 : Symbol(Derived02c03, Decl(genericDefaults.ts, 84, 5))
>Derived02 : Symbol(Derived02, Decl(genericDefaults.ts, 78, 46))

View file

@ -0,0 +1,500 @@
=== tests/cases/compiler/genericDefaults.ts ===
declare const x: any;
>x : any
declare function f00<T = number>(a?: T): T;
>f00 : <T = number>(a?: T) => T
>T : T
>a : T
>T : T
>T : T
const f00c00 = f00();
>f00c00 : number
>f00() : number
>f00 : <T = number>(a?: T) => T
const f00c01 = f00(1);
>f00c01 : 1
>f00(1) : 1
>f00 : <T = number>(a?: T) => T
>1 : 1
const f00c02 = f00("a");
>f00c02 : "a"
>f00("a") : "a"
>f00 : <T = number>(a?: T) => T
>"a" : "a"
const f00c03 = f00<number>();
>f00c03 : number
>f00<number>() : number
>f00 : <T = number>(a?: T) => T
const f00c04 = f00<number>(1);
>f00c04 : number
>f00<number>(1) : number
>f00 : <T = number>(a?: T) => T
>1 : 1
const f00c05 = f00<string>("a");
>f00c05 : string
>f00<string>("a") : string
>f00 : <T = number>(a?: T) => T
>"a" : "a"
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>T : T
>U : U
>T : T
>a : T
>T : T
>b : U
>U : U
>T : T
>U : U
const f01c00 = f01();
>f01c00 : [{}, {}]
>f01() : [{}, {}]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
const f01c01 = f01(1);
>f01c01 : [number, number]
>f01(1) : [number, number]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f01c02 = f01(1, "a");
>f01c02 : [number, string]
>f01(1, "a") : [number, string]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
const f01c03 = f01<number>();
>f01c03 : [number, number]
>f01<number>() : [number, number]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
const f01c04 = f01<number>(1);
>f01c04 : [number, number]
>f01<number>(1) : [number, number]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f01c05 = f01<number>(1, "a");
>f01c05 : [number, string]
>f01<number>(1, "a") : [number, string]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
const f01c06 = f01<number, string>();
>f01c06 : [number, string]
>f01<number, string>() : [number, string]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
const f01c07 = f01<number, string>(1);
>f01c07 : [number, string]
>f01<number, string>(1) : [number, string]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f01c08 = f01<number, string>(1, "a");
>f01c08 : [number, string]
>f01<number, string>(1, "a") : [number, string]
>f01 : <T, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>T : T
>U : U
>T : T
>a : T
>T : T
>b : U
>U : U
>T : T
>U : U
const f02c00 = f02();
>f02c00 : [number, number]
>f02() : [number, number]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
const f02c01 = f02(1);
>f02c01 : [1, 1]
>f02(1) : [1, 1]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f02c02 = f02(1, "a");
>f02c02 : [1, string]
>f02(1, "a") : [1, string]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
const f02c03 = f02<number>();
>f02c03 : [number, number]
>f02<number>() : [number, number]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
const f02c04 = f02<number>(1);
>f02c04 : [number, number]
>f02<number>(1) : [number, number]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f02c05 = f02<number>(1, "a");
>f02c05 : [number, string]
>f02<number>(1, "a") : [number, string]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
const f02c06 = f02<number, string>();
>f02c06 : [number, string]
>f02<number, string>() : [number, string]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
const f02c07 = f02<number, string>(1);
>f02c07 : [number, string]
>f02<number, string>(1) : [number, string]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f02c08 = f02<number, string>(1, "a");
>f02c08 : [number, string]
>f02<number, string>(1, "a") : [number, string]
>f02 : <T extends number, U = T>(a?: T, b?: U) => [T, U]
>1 : 1
>"a" : "a"
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>T : T
>U : U
>T : T
>T : T
>a : T
>T : T
>b : U
>U : U
>T : T
>U : U
const f03c00 = f03();
>f03c00 : [number, number]
>f03() : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
const f03c01 = f03(1);
>f03c01 : [1, 1]
>f03(1) : [1, 1]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f03c02 = f03(1, 1);
>f03c02 : [1, 1]
>f03(1, 1) : [1, 1]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
>1 : 1
const f03c03 = f03<number>();
>f03c03 : [number, number]
>f03<number>() : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
const f03c04 = f03<number>(1);
>f03c04 : [number, number]
>f03<number>(1) : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f03c05 = f03<number>(1, 2);
>f03c05 : [number, number]
>f03<number>(1, 2) : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
>2 : 2
const f03c06 = f03<number, number>();
>f03c06 : [number, number]
>f03<number, number>() : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
const f03c07 = f03<number, number>(1);
>f03c07 : [number, number]
>f03<number, number>(1) : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
const f03c08 = f03<number, number>(1, 2);
>f03c08 : [number, number]
>f03<number, number>(1, 2) : [number, number]
>f03 : <T extends number, U extends T = T>(a?: T, b?: U) => [T, U]
>1 : 1
>2 : 2
interface i00<T = number> { a: T; }
>i00 : i00<T>
>T : T
>a : T
>T : T
const i00c00 = (<i00>x).a;
>i00c00 : number
>(<i00>x).a : number
>(<i00>x) : i00<number>
><i00>x : i00<number>
>i00 : i00<T>
>x : any
>a : number
const i00c01 = (<i00<number>>x).a;
>i00c01 : number
>(<i00<number>>x).a : number
>(<i00<number>>x) : i00<number>
><i00<number>>x : i00<number>
>i00 : i00<T>
>x : any
>a : number
interface i01<T, U = T> { a: [T, U]; }
>i01 : i01<T, U>
>T : T
>U : U
>T : T
>a : [T, U]
>T : T
>U : U
const i01c00 = (<i01<number>>x).a;
>i01c00 : [number, number]
>(<i01<number>>x).a : [number, number]
>(<i01<number>>x) : i01<number, number>
><i01<number>>x : i01<number, number>
>i01 : i01<T, U>
>x : any
>a : [number, number]
const i01c01 = (<i01<number, string>>x).a;
>i01c01 : [number, string]
>(<i01<number, string>>x).a : [number, string]
>(<i01<number, string>>x) : i01<number, string>
><i01<number, string>>x : i01<number, string>
>i01 : i01<T, U>
>x : any
>a : [number, string]
interface i02<T extends number, U = T> { a: [T, U]; }
>i02 : i02<T, U>
>T : T
>U : U
>T : T
>a : [T, U]
>T : T
>U : U
const i02c00 = (<i02<number>>x).a;
>i02c00 : [number, number]
>(<i02<number>>x).a : [number, number]
>(<i02<number>>x) : i02<number, number>
><i02<number>>x : i02<number, number>
>i02 : i02<T, U>
>x : any
>a : [number, number]
const i02c01 = (<i02<1>>x).a;
>i02c01 : [1, 1]
>(<i02<1>>x).a : [1, 1]
>(<i02<1>>x) : i02<1, 1>
><i02<1>>x : i02<1, 1>
>i02 : i02<T, U>
>x : any
>a : [1, 1]
const i02c02 = (<i02<number, number>>x).a;
>i02c02 : [number, number]
>(<i02<number, number>>x).a : [number, number]
>(<i02<number, number>>x) : i02<number, number>
><i02<number, number>>x : i02<number, number>
>i02 : i02<T, U>
>x : any
>a : [number, number]
const i02c03 = (<i02<1, number>>x).a;
>i02c03 : [1, number]
>(<i02<1, number>>x).a : [1, number]
>(<i02<1, number>>x) : i02<1, number>
><i02<1, number>>x : i02<1, number>
>i02 : i02<T, U>
>x : any
>a : [1, number]
const i02c04 = (<i02<number, 1>>x).a;
>i02c04 : [number, 1]
>(<i02<number, 1>>x).a : [number, 1]
>(<i02<number, 1>>x) : i02<number, 1>
><i02<number, 1>>x : i02<number, 1>
>i02 : i02<T, U>
>x : any
>a : [number, 1]
interface i03<T extends number, U extends T = T> { a: [T, U]; }
>i03 : i03<T, U>
>T : T
>U : U
>T : T
>T : T
>a : [T, U]
>T : T
>U : U
const i03c00 = (<i03<number>>x).a;
>i03c00 : [number, number]
>(<i03<number>>x).a : [number, number]
>(<i03<number>>x) : i03<number, number>
><i03<number>>x : i03<number, number>
>i03 : i03<T, U>
>x : any
>a : [number, number]
const i03c01 = (<i03<1>>x).a;
>i03c01 : [1, 1]
>(<i03<1>>x).a : [1, 1]
>(<i03<1>>x) : i03<1, 1>
><i03<1>>x : i03<1, 1>
>i03 : i03<T, U>
>x : any
>a : [1, 1]
const i03c02 = (<i03<number, number>>x).a;
>i03c02 : [number, number]
>(<i03<number, number>>x).a : [number, number]
>(<i03<number, number>>x) : i03<number, number>
><i03<number, number>>x : i03<number, number>
>i03 : i03<T, U>
>x : any
>a : [number, number]
const i03c03 = (<i03<1, 1>>x).a;
>i03c03 : [1, 1]
>(<i03<1, 1>>x).a : [1, 1]
>(<i03<1, 1>>x) : i03<1, 1>
><i03<1, 1>>x : i03<1, 1>
>i03 : i03<T, U>
>x : any
>a : [1, 1]
const i03c04 = (<i03<number, 1>>x).a;
>i03c04 : [number, 1]
>(<i03<number, 1>>x).a : [number, 1]
>(<i03<number, 1>>x) : i03<number, 1>
><i03<number, 1>>x : i03<number, 1>
>i03 : i03<T, U>
>x : any
>a : [number, 1]
interface Base01<T> { a: T; }
>Base01 : Base01<T>
>T : T
>a : T
>T : T
interface Base01Constructor { new <T = number>(a?: T): Base01<T>; }
>Base01Constructor : Base01Constructor
>T : T
>a : T
>T : T
>Base01 : Base01<T>
>T : T
declare const Base01: Base01Constructor;
>Base01 : Base01Constructor
>Base01Constructor : Base01Constructor
const Base01c00 = new Base01();
>Base01c00 : Base01<number>
>new Base01() : Base01<number>
>Base01 : Base01Constructor
const Base01c01 = new Base01(1);
>Base01c01 : Base01<number>
>new Base01(1) : Base01<number>
>Base01 : Base01Constructor
>1 : 1
const Base01c02 = new Base01<number>();
>Base01c02 : Base01<number>
>new Base01<number>() : Base01<number>
>Base01 : Base01Constructor
const Base01c03 = new Base01<number>(1);
>Base01c03 : Base01<number>
>new Base01<number>(1) : Base01<number>
>Base01 : Base01Constructor
>1 : 1
declare class Derived01<T> extends Base01<T> { }
>Derived01 : Derived01<T>
>T : T
>Base01 : Base01<T>
>T : T
const Derived01c00 = new Derived01();
>Derived01c00 : Derived01<{}>
>new Derived01() : Derived01<{}>
>Derived01 : typeof Derived01
const Derived01c01 = new Derived01(1);
>Derived01c01 : Derived01<number>
>new Derived01(1) : Derived01<number>
>Derived01 : typeof Derived01
>1 : 1
const Derived01c02 = new Derived01<number>();
>Derived01c02 : Derived01<number>
>new Derived01<number>() : Derived01<number>
>Derived01 : typeof Derived01
const Derived01c03 = new Derived01<number>(1);
>Derived01c03 : Derived01<number>
>new Derived01<number>(1) : Derived01<number>
>Derived01 : typeof Derived01
>1 : 1
declare class Derived02<T = string> extends Base01<T> { }
>Derived02 : Derived02<T>
>T : T
>Base01 : Base01<T>
>T : T
const Derived02c00 = new Derived02();
>Derived02c00 : Derived02<string>
>new Derived02() : Derived02<string>
>Derived02 : typeof Derived02
const Derived02c01 = new Derived02(1);
>Derived02c01 : Derived02<number>
>new Derived02(1) : Derived02<number>
>Derived02 : typeof Derived02
>1 : 1
const Derived02c02 = new Derived02<number>();
>Derived02c02 : Derived02<number>
>new Derived02<number>() : Derived02<number>
>Derived02 : typeof Derived02
const Derived02c03 = new Derived02<number>(1);
>Derived02c03 : Derived02<number>
>new Derived02<number>(1) : Derived02<number>
>Derived02 : typeof Derived02
>1 : 1

View file

@ -0,0 +1,114 @@
tests/cases/compiler/genericDefaultsErrors.ts(4,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(5,26): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(5,33): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(6,29): error TS2705: Required type parameters may not follow optional type parameters
tests/cases/compiler/genericDefaultsErrors.ts(7,41): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(8,59): error TS2344: Type 'T' does not satisfy the constraint 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(9,44): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(10,39): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(14,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(17,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/genericDefaultsErrors.ts(20,11): error TS2428: All declarations of 'i00' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(23,11): error TS2428: All declarations of 'i01' must have identical type parameters.
tests/cases/compiler/genericDefaultsErrors.ts(25,19): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(26,19): error TS2706: Type parameter 'T' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(26,26): error TS2706: Type parameter 'U' has a circular default.
tests/cases/compiler/genericDefaultsErrors.ts(27,22): error TS2705: Required type parameters may not follow optional type parameters
tests/cases/compiler/genericDefaultsErrors.ts(28,34): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/compiler/genericDefaultsErrors.ts(29,52): error TS2344: Type 'T' does not satisfy the constraint 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(30,37): error TS2344: Type 'T' does not satisfy the constraint 'number'.
tests/cases/compiler/genericDefaultsErrors.ts(31,32): error TS2344: Type 'number' does not satisfy the constraint 'T'.
tests/cases/compiler/genericDefaultsErrors.ts(34,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments
tests/cases/compiler/genericDefaultsErrors.ts(35,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments
tests/cases/compiler/genericDefaultsErrors.ts(38,15): error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments
==== tests/cases/compiler/genericDefaultsErrors.ts (23 errors) ====
declare const x: any;
declare function f00<T = T>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
declare function f01<T = U, U = T>(): void;
~
!!! error TS2706: Type parameter 'T' has a circular default.
~
!!! error TS2706: Type parameter 'U' has a circular default.
declare function f02<T = U, U>();
~
!!! error TS2705: Required type parameters may not follow optional type parameters
declare function f03<T extends string = number>(): void;
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'string'.
declare function f04<T extends string, U extends number = T>(): void;
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
declare function f05<T, U extends number = T>(): void;
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
declare function f06<T, U extends T = number>(): void;
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'T'.
declare function f07<T, U, V = number>(): void;
f07(); // ok
f07<1>(); // error
~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
f07<1, 2>(); // ok
f07<1, 2, 3>(); // ok
f07<1, 2, 3, 4>(); // error
~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
interface i00<T> { }
interface i00<T = number> { }
~~~
!!! error TS2428: All declarations of 'i00' must have identical type parameters.
interface i01<T = number> { }
interface i01<T = string> { }
~~~
!!! error TS2428: All declarations of 'i01' must have identical type parameters.
interface i02<T = T> { }
~
!!! error TS2706: Type parameter 'T' has a circular default.
interface i03<T = U, U = T> { }
~
!!! error TS2706: Type parameter 'T' has a circular default.
~
!!! error TS2706: Type parameter 'U' has a circular default.
interface i04<T = U, U> { }
~
!!! error TS2705: Required type parameters may not follow optional type parameters
interface i05<T extends string = number> { }
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'string'.
interface i06<T extends string, U extends number = T> { }
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
interface i07<T, U extends number = T> { }
~
!!! error TS2344: Type 'T' does not satisfy the constraint 'number'.
interface i08<T, U extends T = number> { }
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'T'.
interface i09<T, U, V = number> { }
type i09t00 = i09; // error
~~~
!!! error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments
type i09t01 = i09<1>; // error
~~~~~~
!!! error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments
type i09t02 = i09<1, 2>; // ok
type i09t03 = i09<1, 2, 3>; // ok
type i09t04 = i09<1, 2, 3, 4>; // error
~~~~~~~~~~~~~~~
!!! error TS2707: Generic type 'i09<T, U, V>' requires between 2 and 3 type arguments

View file

@ -0,0 +1,87 @@
//// [genericDefaultsErrors.ts]
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>();
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T, U, V = number>(): void;
f07(); // ok
f07<1>(); // error
f07<1, 2>(); // ok
f07<1, 2, 3>(); // ok
f07<1, 2, 3, 4>(); // error
interface i00<T> { }
interface i00<T = number> { }
interface i01<T = number> { }
interface i01<T = string> { }
interface i02<T = T> { }
interface i03<T = U, U = T> { }
interface i04<T = U, U> { }
interface i05<T extends string = number> { }
interface i06<T extends string, U extends number = T> { }
interface i07<T, U extends number = T> { }
interface i08<T, U extends T = number> { }
interface i09<T, U, V = number> { }
type i09t00 = i09; // error
type i09t01 = i09<1>; // error
type i09t02 = i09<1, 2>; // ok
type i09t03 = i09<1, 2, 3>; // ok
type i09t04 = i09<1, 2, 3, 4>; // error
//// [genericDefaultsErrors.js]
f07(); // ok
f07(); // error
f07(); // ok
f07(); // ok
f07(); // error
//// [genericDefaultsErrors.d.ts]
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>(): any;
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T, U, V = number>(): void;
interface i00<T> {
}
interface i00<T = number> {
}
interface i01<T = number> {
}
interface i01<T = string> {
}
interface i02<T = T> {
}
interface i03<T = U, U = T> {
}
interface i04<T = U, U> {
}
interface i05<T extends string = number> {
}
interface i06<T extends string, U extends number = T> {
}
interface i07<T, U extends number = T> {
}
interface i08<T, U extends T = number> {
}
interface i09<T, U, V = number> {
}
declare type i09t00 = i09;
declare type i09t01 = i09<1>;
declare type i09t02 = i09<1, 2>;
declare type i09t03 = i09<1, 2, 3>;
declare type i09t04 = i09<1, 2, 3, 4>;

View file

@ -0,0 +1,86 @@
// @declaration: true
declare const x: any;
declare function f00<T = number>(a?: T): T;
const f00c00 = f00();
const f00c01 = f00(1);
const f00c02 = f00("a");
const f00c03 = f00<number>();
const f00c04 = f00<number>(1);
const f00c05 = f00<string>("a");
declare function f01<T, U = T>(a?: T, b?: U): [T, U];
const f01c00 = f01();
const f01c01 = f01(1);
const f01c02 = f01(1, "a");
const f01c03 = f01<number>();
const f01c04 = f01<number>(1);
const f01c05 = f01<number>(1, "a");
const f01c06 = f01<number, string>();
const f01c07 = f01<number, string>(1);
const f01c08 = f01<number, string>(1, "a");
declare function f02<T extends number, U = T>(a?: T, b?: U): [T, U];
const f02c00 = f02();
const f02c01 = f02(1);
const f02c02 = f02(1, "a");
const f02c03 = f02<number>();
const f02c04 = f02<number>(1);
const f02c05 = f02<number>(1, "a");
const f02c06 = f02<number, string>();
const f02c07 = f02<number, string>(1);
const f02c08 = f02<number, string>(1, "a");
declare function f03<T extends number, U extends T = T>(a?: T, b?: U): [T, U];
const f03c00 = f03();
const f03c01 = f03(1);
const f03c02 = f03(1, 1);
const f03c03 = f03<number>();
const f03c04 = f03<number>(1);
const f03c05 = f03<number>(1, 2);
const f03c06 = f03<number, number>();
const f03c07 = f03<number, number>(1);
const f03c08 = f03<number, number>(1, 2);
interface i00<T = number> { a: T; }
const i00c00 = (<i00>x).a;
const i00c01 = (<i00<number>>x).a;
interface i01<T, U = T> { a: [T, U]; }
const i01c00 = (<i01<number>>x).a;
const i01c01 = (<i01<number, string>>x).a;
interface i02<T extends number, U = T> { a: [T, U]; }
const i02c00 = (<i02<number>>x).a;
const i02c01 = (<i02<1>>x).a;
const i02c02 = (<i02<number, number>>x).a;
const i02c03 = (<i02<1, number>>x).a;
const i02c04 = (<i02<number, 1>>x).a;
interface i03<T extends number, U extends T = T> { a: [T, U]; }
const i03c00 = (<i03<number>>x).a;
const i03c01 = (<i03<1>>x).a;
const i03c02 = (<i03<number, number>>x).a;
const i03c03 = (<i03<1, 1>>x).a;
const i03c04 = (<i03<number, 1>>x).a;
interface Base01<T> { a: T; }
interface Base01Constructor { new <T = number>(a?: T): Base01<T>; }
declare const Base01: Base01Constructor;
const Base01c00 = new Base01();
const Base01c01 = new Base01(1);
const Base01c02 = new Base01<number>();
const Base01c03 = new Base01<number>(1);
declare class Derived01<T> extends Base01<T> { }
const Derived01c00 = new Derived01();
const Derived01c01 = new Derived01(1);
const Derived01c02 = new Derived01<number>();
const Derived01c03 = new Derived01<number>(1);
declare class Derived02<T = string> extends Base01<T> { }
const Derived02c00 = new Derived02();
const Derived02c01 = new Derived02(1);
const Derived02c02 = new Derived02<number>();
const Derived02c03 = new Derived02<number>(1);

View file

@ -0,0 +1,39 @@
// @declaration: true
declare const x: any;
declare function f00<T = T>(): void;
declare function f01<T = U, U = T>(): void;
declare function f02<T = U, U>();
declare function f03<T extends string = number>(): void;
declare function f04<T extends string, U extends number = T>(): void;
declare function f05<T, U extends number = T>(): void;
declare function f06<T, U extends T = number>(): void;
declare function f07<T, U, V = number>(): void;
f07(); // ok
f07<1>(); // error
f07<1, 2>(); // ok
f07<1, 2, 3>(); // ok
f07<1, 2, 3, 4>(); // error
interface i00<T> { }
interface i00<T = number> { }
interface i01<T = number> { }
interface i01<T = string> { }
interface i02<T = T> { }
interface i03<T = U, U = T> { }
interface i04<T = U, U> { }
interface i05<T extends string = number> { }
interface i06<T extends string, U extends number = T> { }
interface i07<T, U extends number = T> { }
interface i08<T, U extends T = number> { }
interface i09<T, U, V = number> { }
type i09t00 = i09; // error
type i09t01 = i09<1>; // error
type i09t02 = i09<1, 2>; // ok
type i09t03 = i09<1, 2, 3>; // ok
type i09t04 = i09<1, 2, 3, 4>; // error