Merge branch 'master' into isInMultiLineComment

This commit is contained in:
Arthur Ozga 2017-08-07 15:58:46 -07:00
commit 2f5b1d3e18
44 changed files with 1261 additions and 72 deletions

View file

@ -5788,8 +5788,7 @@ namespace ts {
}
function isGenericMappedType(type: Type) {
return getObjectFlags(type) & ObjectFlags.Mapped &&
maybeTypeOfKind(getConstraintTypeFromMappedType(<MappedType>type), TypeFlags.TypeVariable | TypeFlags.Index);
return getObjectFlags(type) & ObjectFlags.Mapped && isGenericIndexType(getConstraintTypeFromMappedType(<MappedType>type));
}
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
@ -5901,6 +5900,10 @@ namespace ts {
}
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
const transformed = getTransformedIndexedAccessType(type);
if (transformed) {
return transformed;
}
const baseObjectType = getBaseConstraintOfType(type.objectType);
const baseIndexType = getBaseConstraintOfType(type.indexType);
return baseObjectType || baseIndexType ? getIndexedAccessType(baseObjectType || type.objectType, baseIndexType || type.indexType) : undefined;
@ -5972,11 +5975,18 @@ namespace ts {
return stringType;
}
if (t.flags & TypeFlags.IndexedAccess) {
const transformed = getTransformedIndexedAccessType(<IndexedAccessType>t);
if (transformed) {
return getBaseConstraint(transformed);
}
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
const baseIndexType = getBaseConstraint((<IndexedAccessType>t).indexType);
const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined;
return baseIndexedAccess && baseIndexedAccess !== unknownType ? getBaseConstraint(baseIndexedAccess) : undefined;
}
if (isGenericMappedType(t)) {
return emptyObjectType;
}
return t;
}
}
@ -7604,26 +7614,73 @@ namespace ts {
return instantiateType(getTemplateTypeFromMappedType(type), templateMapper);
}
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
// If the index type is generic, if the object type is generic and doesn't originate in an expression,
// or if the object type is a mapped type with a generic constraint, we are performing a higher-order
// index access where we cannot meaningfully access the properties of the object type. Note that for a
// generic T and a non-generic K, we eagerly resolve T[K] if it originates in an expression. This is to
// preserve backwards compatibility. For example, an element access 'this["foo"]' has always been resolved
// eagerly using the constraint type of 'this' at the given location.
if (maybeTypeOfKind(indexType, TypeFlags.TypeVariable | TypeFlags.Index) ||
maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) ||
isGenericMappedType(objectType)) {
function isGenericObjectType(type: Type): boolean {
return type.flags & TypeFlags.TypeVariable ? true :
getObjectFlags(type) & ObjectFlags.Mapped ? isGenericIndexType(getConstraintTypeFromMappedType(<MappedType>type)) :
type.flags & TypeFlags.UnionOrIntersection ? forEach((<UnionOrIntersectionType>type).types, isGenericObjectType) :
false;
}
function isGenericIndexType(type: Type): boolean {
return type.flags & (TypeFlags.TypeVariable | TypeFlags.Index) ? true :
type.flags & TypeFlags.UnionOrIntersection ? forEach((<UnionOrIntersectionType>type).types, isGenericIndexType) :
false;
}
// Return true if the given type is a non-generic object type with a string index signature and no
// other members.
function isStringIndexOnlyType(type: Type) {
if (type.flags & TypeFlags.Object && !isGenericMappedType(type)) {
const t = resolveStructuredTypeMembers(<ObjectType>type);
return t.properties.length === 0 &&
t.callSignatures.length === 0 && t.constructSignatures.length === 0 &&
t.stringIndexInfo && !t.numberIndexInfo;
}
return false;
}
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
// access types with default property values as expressed by D.
function getTransformedIndexedAccessType(type: IndexedAccessType): Type {
const objectType = type.objectType;
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType) && some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
const regularTypes: Type[] = [];
const stringIndexTypes: Type[] = [];
for (const t of (<IntersectionType>objectType).types) {
if (isStringIndexOnlyType(t)) {
stringIndexTypes.push(getIndexTypeOfType(t, IndexKind.String));
}
else {
regularTypes.push(t);
}
}
return getUnionType([
getIndexedAccessType(getIntersectionType(regularTypes), type.indexType),
getIntersectionType(stringIndexTypes)
]);
}
return undefined;
}
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type {
// If the object type is a mapped type { [P in K]: E }, where K is generic, we instantiate E using a mapper
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
// construct the type Box<T[X]>.
if (isGenericMappedType(objectType)) {
return getIndexedAccessForMappedType(<MappedType>objectType, indexType, accessNode);
}
// Otherwise, if the index type is generic, or if the object type is generic and doesn't originate in an
// expression, we are performing a higher-order index access where we cannot meaningfully access the properties
// of the object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates
// in an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]'
// has always been resolved eagerly using the constraint type of 'this' at the given location.
if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) && isGenericObjectType(objectType)) {
if (objectType.flags & TypeFlags.Any) {
return objectType;
}
// If the object type is a mapped type { [P in K]: E }, we instantiate E using a mapper that substitutes
// the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the
// type Box<T[X]>.
if (isGenericMappedType(objectType)) {
return getIndexedAccessForMappedType(<MappedType>objectType, indexType, accessNode);
}
// Otherwise we defer the operation by creating an indexed access type.
// Defer the operation by creating an indexed access type.
const id = objectType.id + "," + indexType.id;
let type = indexedAccessTypes.get(id);
if (!type) {
@ -8017,7 +8074,7 @@ namespace ts {
function cloneTypeMapper(mapper: TypeMapper): TypeMapper {
return mapper && isInferenceContext(mapper) ?
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.compareTypes, mapper.inferences) :
mapper;
}
@ -8458,7 +8515,7 @@ namespace ts {
ignoreReturnTypes: boolean,
reportErrors: boolean,
errorReporter: ErrorReporter,
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
compareTypes: TypeComparer): Ternary {
// TODO (drosen): De-duplicate code between related functions.
if (source === target) {
return Ternary.True;
@ -8468,7 +8525,7 @@ namespace ts {
}
if (source.typeParameters) {
source = instantiateSignatureInContextOf(source, target);
source = instantiateSignatureInContextOf(source, target, /*contextualMapper*/ undefined, compareTypes);
}
let result = Ternary.True;
@ -9614,6 +9671,11 @@ namespace ts {
if (sourceInfo) {
return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors);
}
if (isGenericMappedType(source)) {
// A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U }
// if T is related to U.
return kind === IndexKind.String && isRelatedTo(getTemplateTypeFromMappedType(<MappedType>source), targetInfo.type, reportErrors);
}
if (isObjectLiteralType(source)) {
let related = Ternary.True;
if (kind === IndexKind.String) {
@ -10216,13 +10278,14 @@ namespace ts {
}
}
function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
function createInferenceContext(signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
const context = mapper as InferenceContext;
context.mappedTypes = signature.typeParameters;
context.signature = signature;
context.inferences = inferences;
context.flags = flags;
context.compareTypes = compareTypes || compareTypesAssignable;
return context;
function mapper(t: Type): Type {
@ -10325,6 +10388,19 @@ namespace ts {
}
}
function isPossiblyAssignableTo(source: Type, target: Type) {
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {
if (!(targetProp.flags & (SymbolFlags.Optional | SymbolFlags.Prototype))) {
const sourceProp = getPropertyOfObjectType(source, targetProp.escapedName);
if (!sourceProp) {
return false;
}
}
}
return true;
}
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
let symbolStack: Symbol[];
let visited: Map<boolean>;
@ -10518,10 +10594,14 @@ namespace ts {
return;
}
}
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
// Infer from the members of source and target only if the two types are possibly related. We check
// in both directions because we may be inferring for a co-variant or a contra-variant position.
if (isPossiblyAssignableTo(source, target) || isPossiblyAssignableTo(target, source)) {
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target);
}
}
function inferFromProperties(source: Type, target: Type) {
@ -10653,7 +10733,7 @@ namespace ts {
const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]);
if (constraint) {
const instantiatedConstraint = instantiateType(constraint, context);
if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
inference.inferredType = inferredType = instantiatedConstraint;
}
}
@ -15054,8 +15134,8 @@ namespace ts {
}
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper): Signature {
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes);
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature {
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes, compareTypes);
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target);

View file

@ -11,20 +11,6 @@ namespace ts {
/* @internal */
namespace ts {
/**
* Ternary values are defined such that
* x & y is False if either x or y is False.
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
* x & y is True if both x and y are True.
* x | y is False if both x and y are False.
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
* x | y is True if either x or y is True.
*/
export const enum Ternary {
False = 0,
Maybe = 1,
True = -1
}
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }) : undefined;

View file

@ -1346,7 +1346,9 @@ namespace ts {
emitExpression(node.left);
increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined);
emitLeadingCommentsOfPosition(node.operatorToken.pos);
writeTokenNode(node.operatorToken);
emitTrailingCommentsOfPosition(node.operatorToken.end);
increaseIndentIf(indentAfterOperator, " ");
emitExpression(node.right);
decreaseIndentIf(indentBeforeOperator, indentAfterOperator);

View file

@ -2061,7 +2061,7 @@ namespace ts {
return <TemplateMiddle | TemplateTail>fragment;
}
function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
function parseLiteralLikeNode(kind: SyntaxKind): LiteralExpression | LiteralLikeNode {
const node = <LiteralExpression>createNode(kind);
const text = scanner.getTokenValue();
node.text = text;
@ -2611,11 +2611,31 @@ namespace ts {
return token() === SyntaxKind.DotToken ? undefined : node;
}
function parseLiteralTypeNode(): LiteralTypeNode {
const node = <LiteralTypeNode>createNode(SyntaxKind.LiteralType);
node.literal = parseSimpleUnaryExpression();
finishNode(node);
return node;
function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode;
let unaryMinusExpression: PrefixUnaryExpression;
if (negative) {
unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression;
unaryMinusExpression.operator = SyntaxKind.MinusToken;
nextToken();
}
let expression: UnaryExpression;
switch (token()) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
expression = parseLiteralLikeNode(token()) as LiteralExpression;
break;
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
expression = parseTokenNode();
}
if (negative) {
unaryMinusExpression.operand = expression;
finishNode(unaryMinusExpression);
expression = unaryMinusExpression;
}
node.literal = expression;
return finishNode(node);
}
function nextTokenIsNumericLiteral() {
@ -2650,7 +2670,7 @@ namespace ts {
case SyntaxKind.FalseKeyword:
return parseLiteralTypeNode();
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode() : parseTypeReference();
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();

View file

@ -3425,11 +3425,29 @@ namespace ts {
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
}
/**
* Ternary values are defined such that
* x & y is False if either x or y is False.
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
* x & y is True if both x and y are True.
* x | y is False if both x and y are False.
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
* x | y is True if either x or y is True.
*/
export const enum Ternary {
False = 0,
Maybe = 1,
True = -1
}
export type TypeComparer = (s: Type, t: Type, reportErrors?: boolean) => Ternary;
/* @internal */
export interface InferenceContext extends TypeMapper {
signature: Signature; // Generic signature for which inferences are made
inferences: InferenceInfo[]; // Inferences made for each type parameter
flags: InferenceFlags; // Inference flags
compareTypes: TypeComparer; // Type comparer function
}
/* @internal */

View file

@ -1000,7 +1000,7 @@ namespace ts.Completions {
const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
if (!typeForObject) return false;
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
typeMembers = typeChecker.getPropertiesOfType(typeForObject);
typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter((symbol) => !(getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.NonPublicAccessibilityModifier));
existingMembers = (<ObjectBindingPattern>objectLikeContainer).elements;
}
}

View file

@ -0,0 +1,25 @@
//// [commentOnBinaryOperator1.ts]
var a = 'some'
// comment
+ 'text';
var b = 'some'
/* comment */
+ 'text';
var c = 'some'
/* comment */
+ /*comment1*/
'text';
//// [commentOnBinaryOperator1.js]
var a = 'some'
// comment
+ 'text';
var b = 'some'
/* comment */
+ 'text';
var c = 'some'
/* comment */
+/*comment1*/
'text';

View file

@ -0,0 +1,19 @@
=== tests/cases/compiler/commentOnBinaryOperator1.ts ===
var a = 'some'
>a : Symbol(a, Decl(commentOnBinaryOperator1.ts, 0, 3))
// comment
+ 'text';
var b = 'some'
>b : Symbol(b, Decl(commentOnBinaryOperator1.ts, 4, 3))
/* comment */
+ 'text';
var c = 'some'
>c : Symbol(c, Decl(commentOnBinaryOperator1.ts, 8, 3))
/* comment */
+ /*comment1*/
'text';

View file

@ -0,0 +1,29 @@
=== tests/cases/compiler/commentOnBinaryOperator1.ts ===
var a = 'some'
>a : string
>'some' // comment + 'text' : string
>'some' : "some"
// comment
+ 'text';
>'text' : "text"
var b = 'some'
>b : string
>'some' /* comment */ + 'text' : string
>'some' : "some"
/* comment */
+ 'text';
>'text' : "text"
var c = 'some'
>c : string
>'some' /* comment */ + /*comment1*/ 'text' : string
>'some' : "some"
/* comment */
+ /*comment1*/
'text';
>'text' : "text"

View file

@ -0,0 +1,22 @@
//// [commentOnBinaryOperator2.ts]
var a = 'some'
// comment
+ 'text';
var b = 'some'
/* comment */
+ 'text';
var c = 'some'
/* comment */
+ /*comment1*/
'text';
//// [commentOnBinaryOperator2.js]
var a = 'some'
+ 'text';
var b = 'some'
+ 'text';
var c = 'some'
+
'text';

View file

@ -0,0 +1,19 @@
=== tests/cases/compiler/commentOnBinaryOperator2.ts ===
var a = 'some'
>a : Symbol(a, Decl(commentOnBinaryOperator2.ts, 0, 3))
// comment
+ 'text';
var b = 'some'
>b : Symbol(b, Decl(commentOnBinaryOperator2.ts, 4, 3))
/* comment */
+ 'text';
var c = 'some'
>c : Symbol(c, Decl(commentOnBinaryOperator2.ts, 8, 3))
/* comment */
+ /*comment1*/
'text';

View file

@ -0,0 +1,29 @@
=== tests/cases/compiler/commentOnBinaryOperator2.ts ===
var a = 'some'
>a : string
>'some' // comment + 'text' : string
>'some' : "some"
// comment
+ 'text';
>'text' : "text"
var b = 'some'
>b : string
>'some' /* comment */ + 'text' : string
>'some' : "some"
/* comment */
+ 'text';
>'text' : "text"
var c = 'some'
>c : string
>'some' /* comment */ + /*comment1*/ 'text' : string
>'some' : "some"
/* comment */
+ /*comment1*/
'text';
>'text' : "text"

View file

@ -14,7 +14,7 @@ foo(
function foo(/*c1*/ x, /*d1*/ y, /*e1*/ w) { }
var a, b;
foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b);
foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + b);
foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a +/*e3*/ b);
foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b));
foo(
/*c4*/ function () { },

View file

@ -0,0 +1,64 @@
//// [deferredLookupTypeResolution.ts]
// Repro from #17456
type StringContains<S extends string, L extends string> = (
{ [K in S]: 'true' } &
{ [key: string]: 'false' }
)[L]
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>
type First<T> = ObjectHasKey<T, '0'>; // Should be deferred
type T1 = ObjectHasKey<{ a: string }, 'a'>; // 'true'
type T2 = ObjectHasKey<{ a: string }, 'b'>; // 'false'
// Verify that mapped type isn't eagerly resolved in type-to-string operation
declare function f1<A extends string, B extends string>(a: A, b: B): { [P in A | B]: any };
function f2<A extends string>(a: A) {
return f1(a, 'x');
}
function f3(x: 'a' | 'b') {
return f2(x);
}
//// [deferredLookupTypeResolution.js]
"use strict";
// Repro from #17456
function f2(a) {
return f1(a, 'x');
}
function f3(x) {
return f2(x);
}
//// [deferredLookupTypeResolution.d.ts]
declare type StringContains<S extends string, L extends string> = ({
[K in S]: 'true';
} & {
[key: string]: 'false';
})[L];
declare type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>;
declare type First<T> = ObjectHasKey<T, '0'>;
declare type T1 = ObjectHasKey<{
a: string;
}, 'a'>;
declare type T2 = ObjectHasKey<{
a: string;
}, 'b'>;
declare function f1<A extends string, B extends string>(a: A, b: B): {
[P in A | B]: any;
};
declare function f2<A extends string>(a: A): {
[P in A | "x"]: any;
};
declare function f3(x: 'a' | 'b'): {
a: any;
b: any;
x: any;
};

View file

@ -0,0 +1,76 @@
=== tests/cases/compiler/deferredLookupTypeResolution.ts ===
// Repro from #17456
type StringContains<S extends string, L extends string> = (
>StringContains : Symbol(StringContains, Decl(deferredLookupTypeResolution.ts, 0, 0))
>S : Symbol(S, Decl(deferredLookupTypeResolution.ts, 2, 20))
>L : Symbol(L, Decl(deferredLookupTypeResolution.ts, 2, 37))
{ [K in S]: 'true' } &
>K : Symbol(K, Decl(deferredLookupTypeResolution.ts, 3, 7))
>S : Symbol(S, Decl(deferredLookupTypeResolution.ts, 2, 20))
{ [key: string]: 'false' }
>key : Symbol(key, Decl(deferredLookupTypeResolution.ts, 4, 7))
)[L]
>L : Symbol(L, Decl(deferredLookupTypeResolution.ts, 2, 37))
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>
>ObjectHasKey : Symbol(ObjectHasKey, Decl(deferredLookupTypeResolution.ts, 5, 6))
>O : Symbol(O, Decl(deferredLookupTypeResolution.ts, 7, 18))
>L : Symbol(L, Decl(deferredLookupTypeResolution.ts, 7, 20))
>StringContains : Symbol(StringContains, Decl(deferredLookupTypeResolution.ts, 0, 0))
>O : Symbol(O, Decl(deferredLookupTypeResolution.ts, 7, 18))
>L : Symbol(L, Decl(deferredLookupTypeResolution.ts, 7, 20))
type First<T> = ObjectHasKey<T, '0'>; // Should be deferred
>First : Symbol(First, Decl(deferredLookupTypeResolution.ts, 7, 67))
>T : Symbol(T, Decl(deferredLookupTypeResolution.ts, 9, 11))
>ObjectHasKey : Symbol(ObjectHasKey, Decl(deferredLookupTypeResolution.ts, 5, 6))
>T : Symbol(T, Decl(deferredLookupTypeResolution.ts, 9, 11))
type T1 = ObjectHasKey<{ a: string }, 'a'>; // 'true'
>T1 : Symbol(T1, Decl(deferredLookupTypeResolution.ts, 9, 37))
>ObjectHasKey : Symbol(ObjectHasKey, Decl(deferredLookupTypeResolution.ts, 5, 6))
>a : Symbol(a, Decl(deferredLookupTypeResolution.ts, 11, 24))
type T2 = ObjectHasKey<{ a: string }, 'b'>; // 'false'
>T2 : Symbol(T2, Decl(deferredLookupTypeResolution.ts, 11, 43))
>ObjectHasKey : Symbol(ObjectHasKey, Decl(deferredLookupTypeResolution.ts, 5, 6))
>a : Symbol(a, Decl(deferredLookupTypeResolution.ts, 12, 24))
// Verify that mapped type isn't eagerly resolved in type-to-string operation
declare function f1<A extends string, B extends string>(a: A, b: B): { [P in A | B]: any };
>f1 : Symbol(f1, Decl(deferredLookupTypeResolution.ts, 12, 43))
>A : Symbol(A, Decl(deferredLookupTypeResolution.ts, 16, 20))
>B : Symbol(B, Decl(deferredLookupTypeResolution.ts, 16, 37))
>a : Symbol(a, Decl(deferredLookupTypeResolution.ts, 16, 56))
>A : Symbol(A, Decl(deferredLookupTypeResolution.ts, 16, 20))
>b : Symbol(b, Decl(deferredLookupTypeResolution.ts, 16, 61))
>B : Symbol(B, Decl(deferredLookupTypeResolution.ts, 16, 37))
>P : Symbol(P, Decl(deferredLookupTypeResolution.ts, 16, 72))
>A : Symbol(A, Decl(deferredLookupTypeResolution.ts, 16, 20))
>B : Symbol(B, Decl(deferredLookupTypeResolution.ts, 16, 37))
function f2<A extends string>(a: A) {
>f2 : Symbol(f2, Decl(deferredLookupTypeResolution.ts, 16, 91))
>A : Symbol(A, Decl(deferredLookupTypeResolution.ts, 18, 12))
>a : Symbol(a, Decl(deferredLookupTypeResolution.ts, 18, 30))
>A : Symbol(A, Decl(deferredLookupTypeResolution.ts, 18, 12))
return f1(a, 'x');
>f1 : Symbol(f1, Decl(deferredLookupTypeResolution.ts, 12, 43))
>a : Symbol(a, Decl(deferredLookupTypeResolution.ts, 18, 30))
}
function f3(x: 'a' | 'b') {
>f3 : Symbol(f3, Decl(deferredLookupTypeResolution.ts, 20, 1))
>x : Symbol(x, Decl(deferredLookupTypeResolution.ts, 22, 12))
return f2(x);
>f2 : Symbol(f2, Decl(deferredLookupTypeResolution.ts, 16, 91))
>x : Symbol(x, Decl(deferredLookupTypeResolution.ts, 22, 12))
}

View file

@ -0,0 +1,79 @@
=== tests/cases/compiler/deferredLookupTypeResolution.ts ===
// Repro from #17456
type StringContains<S extends string, L extends string> = (
>StringContains : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>S : S
>L : L
{ [K in S]: 'true' } &
>K : K
>S : S
{ [key: string]: 'false' }
>key : string
)[L]
>L : L
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>
>ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>O : O
>L : L
>StringContains : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>O : O
>L : L
type First<T> = ObjectHasKey<T, '0'>; // Should be deferred
>First : ({ [K in S]: "true"; } & { [key: string]: "false"; })["0"]
>T : T
>ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>T : T
type T1 = ObjectHasKey<{ a: string }, 'a'>; // 'true'
>T1 : "true"
>ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>a : string
type T2 = ObjectHasKey<{ a: string }, 'b'>; // 'false'
>T2 : "false"
>ObjectHasKey : ({ [K in S]: "true"; } & { [key: string]: "false"; })[L]
>a : string
// Verify that mapped type isn't eagerly resolved in type-to-string operation
declare function f1<A extends string, B extends string>(a: A, b: B): { [P in A | B]: any };
>f1 : <A extends string, B extends string>(a: A, b: B) => { [P in A | B]: any; }
>A : A
>B : B
>a : A
>A : A
>b : B
>B : B
>P : P
>A : A
>B : B
function f2<A extends string>(a: A) {
>f2 : <A extends string>(a: A) => { [P in A | B]: any; }
>A : A
>a : A
>A : A
return f1(a, 'x');
>f1(a, 'x') : { [P in A | B]: any; }
>f1 : <A extends string, B extends string>(a: A, b: B) => { [P in A | B]: any; }
>a : A
>'x' : "x"
}
function f3(x: 'a' | 'b') {
>f3 : (x: "a" | "b") => { a: any; b: any; x: any; }
>x : "a" | "b"
return f2(x);
>f2(x) : { a: any; b: any; x: any; }
>f2 : <A extends string>(a: A) => { [P in A | B]: any; }
>x : "a" | "b"
}

View file

@ -0,0 +1,31 @@
tests/cases/compiler/deferredLookupTypeResolution2.ts(14,13): error TS2536: Type '({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'.
tests/cases/compiler/deferredLookupTypeResolution2.ts(19,21): error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'.
==== tests/cases/compiler/deferredLookupTypeResolution2.ts (2 errors) ====
// Repro from #17456
type StringContains<S extends string, L extends string> = ({ [K in S]: 'true' } & { [key: string]: 'false'})[L];
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>;
type A<T> = ObjectHasKey<T, '0'>;
type B = ObjectHasKey<[string, number], '1'>; // "true"
type C = ObjectHasKey<[string, number], '2'>; // "false"
type D = A<[string]>; // "true"
// Error, "false" not handled
type E<T> = { true: 'true' }[ObjectHasKey<T, '1'>];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2536: Type '({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]' cannot be used to index type '{ true: "true"; }'.
type Juxtapose<T> = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey<T, '1'>];
// Error, "otherwise" is missing
type DeepError<T> = { true: 'true' }[Juxtapose<T>];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2536: Type '({ true: "otherwise"; } & { [k: string]: "true"; })[({ [K in S]: "true"; } & { [key: string]: "false"; })["1"]]' cannot be used to index type '{ true: "true"; }'.
type DeepOK<T> = { true: 'true', otherwise: 'false' }[Juxtapose<T>];

View file

@ -0,0 +1,55 @@
//// [deferredLookupTypeResolution2.ts]
// Repro from #17456
type StringContains<S extends string, L extends string> = ({ [K in S]: 'true' } & { [key: string]: 'false'})[L];
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>;
type A<T> = ObjectHasKey<T, '0'>;
type B = ObjectHasKey<[string, number], '1'>; // "true"
type C = ObjectHasKey<[string, number], '2'>; // "false"
type D = A<[string]>; // "true"
// Error, "false" not handled
type E<T> = { true: 'true' }[ObjectHasKey<T, '1'>];
type Juxtapose<T> = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey<T, '1'>];
// Error, "otherwise" is missing
type DeepError<T> = { true: 'true' }[Juxtapose<T>];
type DeepOK<T> = { true: 'true', otherwise: 'false' }[Juxtapose<T>];
//// [deferredLookupTypeResolution2.js]
"use strict";
// Repro from #17456
//// [deferredLookupTypeResolution2.d.ts]
declare type StringContains<S extends string, L extends string> = ({
[K in S]: 'true';
} & {
[key: string]: 'false';
})[L];
declare type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>;
declare type A<T> = ObjectHasKey<T, '0'>;
declare type B = ObjectHasKey<[string, number], '1'>;
declare type C = ObjectHasKey<[string, number], '2'>;
declare type D = A<[string]>;
declare type E<T> = {
true: 'true';
}[ObjectHasKey<T, '1'>];
declare type Juxtapose<T> = ({
true: 'otherwise';
} & {
[k: string]: 'true';
})[ObjectHasKey<T, '1'>];
declare type DeepError<T> = {
true: 'true';
}[Juxtapose<T>];
declare type DeepOK<T> = {
true: 'true';
otherwise: 'false';
}[Juxtapose<T>];

View file

@ -0,0 +1,11 @@
//// [doNotInferUnrelatedTypes.ts]
// #16709
declare function dearray<T>(ara: ReadonlyArray<T>): T;
type LiteralType = "foo" | "bar";
declare var alt: Array<LiteralType>;
let foo: LiteralType = dearray(alt);
//// [doNotInferUnrelatedTypes.js]
var foo = dearray(alt);

View file

@ -0,0 +1,24 @@
=== tests/cases/compiler/doNotInferUnrelatedTypes.ts ===
// #16709
declare function dearray<T>(ara: ReadonlyArray<T>): T;
>dearray : Symbol(dearray, Decl(doNotInferUnrelatedTypes.ts, 0, 0))
>T : Symbol(T, Decl(doNotInferUnrelatedTypes.ts, 1, 25))
>ara : Symbol(ara, Decl(doNotInferUnrelatedTypes.ts, 1, 28))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(doNotInferUnrelatedTypes.ts, 1, 25))
>T : Symbol(T, Decl(doNotInferUnrelatedTypes.ts, 1, 25))
type LiteralType = "foo" | "bar";
>LiteralType : Symbol(LiteralType, Decl(doNotInferUnrelatedTypes.ts, 1, 54))
declare var alt: Array<LiteralType>;
>alt : Symbol(alt, Decl(doNotInferUnrelatedTypes.ts, 3, 11))
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>LiteralType : Symbol(LiteralType, Decl(doNotInferUnrelatedTypes.ts, 1, 54))
let foo: LiteralType = dearray(alt);
>foo : Symbol(foo, Decl(doNotInferUnrelatedTypes.ts, 5, 3))
>LiteralType : Symbol(LiteralType, Decl(doNotInferUnrelatedTypes.ts, 1, 54))
>dearray : Symbol(dearray, Decl(doNotInferUnrelatedTypes.ts, 0, 0))
>alt : Symbol(alt, Decl(doNotInferUnrelatedTypes.ts, 3, 11))

View file

@ -0,0 +1,25 @@
=== tests/cases/compiler/doNotInferUnrelatedTypes.ts ===
// #16709
declare function dearray<T>(ara: ReadonlyArray<T>): T;
>dearray : <T>(ara: ReadonlyArray<T>) => T
>T : T
>ara : ReadonlyArray<T>
>ReadonlyArray : ReadonlyArray<T>
>T : T
>T : T
type LiteralType = "foo" | "bar";
>LiteralType : LiteralType
declare var alt: Array<LiteralType>;
>alt : LiteralType[]
>Array : T[]
>LiteralType : LiteralType
let foo: LiteralType = dearray(alt);
>foo : LiteralType
>LiteralType : LiteralType
>dearray(alt) : LiteralType
>dearray : <T>(ara: ReadonlyArray<T>) => T
>alt : LiteralType[]

View file

@ -0,0 +1,90 @@
tests/cases/compiler/base.d.ts(1,23): error TS1005: ',' expected.
tests/cases/compiler/base.d.ts(1,34): error TS1005: '=' expected.
tests/cases/compiler/boolean.ts(7,23): error TS1005: ',' expected.
tests/cases/compiler/boolean.ts(7,24): error TS1134: Variable declaration expected.
tests/cases/compiler/boolean.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/boolean.ts(12,22): error TS1005: ';' expected.
tests/cases/compiler/number.ts(7,26): error TS1005: ',' expected.
tests/cases/compiler/number.ts(7,27): error TS1134: Variable declaration expected.
tests/cases/compiler/number.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/number.ts(12,20): error TS1005: ';' expected.
tests/cases/compiler/string.ts(7,20): error TS1005: ',' expected.
tests/cases/compiler/string.ts(7,21): error TS1134: Variable declaration expected.
tests/cases/compiler/string.ts(11,15): error TS2304: Cannot find name 'document'.
tests/cases/compiler/string.ts(12,19): error TS1005: ';' expected.
==== tests/cases/compiler/base.d.ts (2 errors) ====
declare const x: "foo".charCodeAt(0);
~
!!! error TS1005: ',' expected.
~
!!! error TS1005: '=' expected.
==== tests/cases/compiler/string.ts (4 errors) ====
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType = "".typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.
==== tests/cases/compiler/number.ts (4 errors) ====
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes2 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType2 = 4..typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.
==== tests/cases/compiler/boolean.ts (4 errors) ====
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes3 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType3 = true.typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.

View file

@ -0,0 +1,85 @@
//// [tests/cases/compiler/expressionTypeNodeShouldError.ts] ////
//// [base.d.ts]
declare const x: "foo".charCodeAt(0);
//// [string.ts]
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
}
}
const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));
//// [number.ts]
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}
const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));
//// [boolean.ts]
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
}
}
const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));
//// [string.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C;
}());
var nodes = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [number.js]
var C2 = (function () {
function C2() {
}
C2.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C2;
}());
var nodes2 = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [boolean.js]
var C3 = (function () {
function C3() {
}
C3.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C3;
}());
var nodes3 = document.getElementsByTagName("li");
typeof (nodes.item(0));

View file

@ -0,0 +1,47 @@
tests/cases/compiler/indexSignatureAndMappedType.ts(6,5): error TS2322: Type '{ [key: string]: T; }' is not assignable to type 'Record<K, T>'.
tests/cases/compiler/indexSignatureAndMappedType.ts(15,5): error TS2322: Type 'Record<K, U>' is not assignable to type '{ [key: string]: T; }'.
Type 'U' is not assignable to type 'T'.
tests/cases/compiler/indexSignatureAndMappedType.ts(16,5): error TS2322: Type '{ [key: string]: T; }' is not assignable to type 'Record<K, U>'.
==== tests/cases/compiler/indexSignatureAndMappedType.ts (3 errors) ====
// A mapped type { [P in K]: X }, where K is a generic type, is related to
// { [key: string]: Y } if X is related to Y.
function f1<T, K extends string>(x: { [key: string]: T }, y: Record<K, T>) {
x = y;
y = x; // Error
~
!!! error TS2322: Type '{ [key: string]: T; }' is not assignable to type 'Record<K, T>'.
}
function f2<T>(x: { [key: string]: T }, y: Record<string, T>) {
x = y;
y = x;
}
function f3<T, U, K extends string>(x: { [key: string]: T }, y: Record<K, U>) {
x = y; // Error
~
!!! error TS2322: Type 'Record<K, U>' is not assignable to type '{ [key: string]: T; }'.
!!! error TS2322: Type 'U' is not assignable to type 'T'.
y = x; // Error
~
!!! error TS2322: Type '{ [key: string]: T; }' is not assignable to type 'Record<K, U>'.
}
// Repro from #14548
type Dictionary = {
[key: string]: string;
};
interface IBaseEntity {
name: string;
properties: Dictionary;
}
interface IEntity<T extends string> extends IBaseEntity {
properties: Record<T, string>;
}

View file

@ -0,0 +1,73 @@
//// [indexSignatureAndMappedType.ts]
// A mapped type { [P in K]: X }, where K is a generic type, is related to
// { [key: string]: Y } if X is related to Y.
function f1<T, K extends string>(x: { [key: string]: T }, y: Record<K, T>) {
x = y;
y = x; // Error
}
function f2<T>(x: { [key: string]: T }, y: Record<string, T>) {
x = y;
y = x;
}
function f3<T, U, K extends string>(x: { [key: string]: T }, y: Record<K, U>) {
x = y; // Error
y = x; // Error
}
// Repro from #14548
type Dictionary = {
[key: string]: string;
};
interface IBaseEntity {
name: string;
properties: Dictionary;
}
interface IEntity<T extends string> extends IBaseEntity {
properties: Record<T, string>;
}
//// [indexSignatureAndMappedType.js]
"use strict";
// A mapped type { [P in K]: X }, where K is a generic type, is related to
// { [key: string]: Y } if X is related to Y.
function f1(x, y) {
x = y;
y = x; // Error
}
function f2(x, y) {
x = y;
y = x;
}
function f3(x, y) {
x = y; // Error
y = x; // Error
}
//// [indexSignatureAndMappedType.d.ts]
declare function f1<T, K extends string>(x: {
[key: string]: T;
}, y: Record<K, T>): void;
declare function f2<T>(x: {
[key: string]: T;
}, y: Record<string, T>): void;
declare function f3<T, U, K extends string>(x: {
[key: string]: T;
}, y: Record<K, U>): void;
declare type Dictionary = {
[key: string]: string;
};
interface IBaseEntity {
name: string;
properties: Dictionary;
}
interface IEntity<T extends string> extends IBaseEntity {
properties: Record<T, string>;
}

View file

@ -97,7 +97,7 @@ var a;
/** @type {string} */
var s;
var a = ("" + 4);
var s = "" + (4);
var s = "" +/** @type {*} */ (4);
var SomeBase = (function () {
function SomeBase() {
this.p = 42;
@ -128,19 +128,19 @@ var someBase = new SomeBase();
var someDerived = new SomeDerived();
var someOther = new SomeOther();
var someFakeClass = new SomeFakeClass();
someBase = (someDerived);
someBase = (someBase);
someBase = (someOther); // Error
someDerived = (someDerived);
someDerived = (someBase);
someDerived = (someOther); // Error
someOther = (someDerived); // Error
someOther = (someBase); // Error
someOther = (someOther);
someBase =/** @type {SomeBase} */ (someDerived);
someBase =/** @type {SomeBase} */ (someBase);
someBase =/** @type {SomeBase} */ (someOther); // Error
someDerived =/** @type {SomeDerived} */ (someDerived);
someDerived =/** @type {SomeDerived} */ (someBase);
someDerived =/** @type {SomeDerived} */ (someOther); // Error
someOther =/** @type {SomeOther} */ (someDerived); // Error
someOther =/** @type {SomeOther} */ (someBase); // Error
someOther =/** @type {SomeOther} */ (someOther);
someFakeClass = someBase;
someFakeClass = someDerived;
someBase = someFakeClass; // Error
someBase = (someFakeClass);
someBase =/** @type {SomeBase} */ (someFakeClass);
// Type assertion cannot be a type-predicate type
/** @type {number | string} */
var numOrStr;

View file

@ -41,9 +41,9 @@ function testcase() {
var one = 1;
var _float = -(4 / 3);
var a = new Array(false, undefined, null, "0", obj, -1.3333333333333, "str", -0, true, +0, one, 1, 0, false, _float, -(4 / 3));
if (a.indexOf(-(4 / 3)) === 14 &&
a.indexOf(0) === 7 &&
a.indexOf(-0) === 7 &&
if (a.indexOf(-(4 / 3)) === 14 &&// a[14]=_float===-(4/3)
a.indexOf(0) === 7 &&// a[7] = +0, 0===+0
a.indexOf(-0) === 7 &&// a[7] = +0, -0===+0
a.indexOf(1) === 10) {
return true;
}

View file

@ -6,5 +6,6 @@
//// [parserGreaterThanTokenAmbiguity10.js]
1
>>>
// before
>>>// after
2;

View file

@ -6,5 +6,6 @@
//// [parserGreaterThanTokenAmbiguity15.js]
1
>>=
// before
>>=// after
2;

View file

@ -6,5 +6,6 @@
//// [parserGreaterThanTokenAmbiguity20.js]
1
>>>=
// Before
>>>=// after
2;

View file

@ -6,5 +6,6 @@
//// [parserGreaterThanTokenAmbiguity5.js]
1
>>
// before
>>// after
2;

View file

@ -0,0 +1,30 @@
//// [signatureInstantiationWithRecursiveConstraints.ts]
// Repro from #17148
class Foo {
myFunc<T extends Foo>(arg: T) {}
}
class Bar {
myFunc<T extends Bar>(arg: T) {}
}
const myVar: Foo = new Bar();
//// [signatureInstantiationWithRecursiveConstraints.js]
"use strict";
// Repro from #17148
var Foo = (function () {
function Foo() {
}
Foo.prototype.myFunc = function (arg) { };
return Foo;
}());
var Bar = (function () {
function Bar() {
}
Bar.prototype.myFunc = function (arg) { };
return Bar;
}());
var myVar = new Bar();

View file

@ -0,0 +1,30 @@
=== tests/cases/compiler/signatureInstantiationWithRecursiveConstraints.ts ===
// Repro from #17148
class Foo {
>Foo : Symbol(Foo, Decl(signatureInstantiationWithRecursiveConstraints.ts, 0, 0))
myFunc<T extends Foo>(arg: T) {}
>myFunc : Symbol(Foo.myFunc, Decl(signatureInstantiationWithRecursiveConstraints.ts, 2, 11))
>T : Symbol(T, Decl(signatureInstantiationWithRecursiveConstraints.ts, 3, 9))
>Foo : Symbol(Foo, Decl(signatureInstantiationWithRecursiveConstraints.ts, 0, 0))
>arg : Symbol(arg, Decl(signatureInstantiationWithRecursiveConstraints.ts, 3, 24))
>T : Symbol(T, Decl(signatureInstantiationWithRecursiveConstraints.ts, 3, 9))
}
class Bar {
>Bar : Symbol(Bar, Decl(signatureInstantiationWithRecursiveConstraints.ts, 4, 1))
myFunc<T extends Bar>(arg: T) {}
>myFunc : Symbol(Bar.myFunc, Decl(signatureInstantiationWithRecursiveConstraints.ts, 6, 11))
>T : Symbol(T, Decl(signatureInstantiationWithRecursiveConstraints.ts, 7, 9))
>Bar : Symbol(Bar, Decl(signatureInstantiationWithRecursiveConstraints.ts, 4, 1))
>arg : Symbol(arg, Decl(signatureInstantiationWithRecursiveConstraints.ts, 7, 24))
>T : Symbol(T, Decl(signatureInstantiationWithRecursiveConstraints.ts, 7, 9))
}
const myVar: Foo = new Bar();
>myVar : Symbol(myVar, Decl(signatureInstantiationWithRecursiveConstraints.ts, 10, 5))
>Foo : Symbol(Foo, Decl(signatureInstantiationWithRecursiveConstraints.ts, 0, 0))
>Bar : Symbol(Bar, Decl(signatureInstantiationWithRecursiveConstraints.ts, 4, 1))

View file

@ -0,0 +1,31 @@
=== tests/cases/compiler/signatureInstantiationWithRecursiveConstraints.ts ===
// Repro from #17148
class Foo {
>Foo : Foo
myFunc<T extends Foo>(arg: T) {}
>myFunc : <T extends Foo>(arg: T) => void
>T : T
>Foo : Foo
>arg : T
>T : T
}
class Bar {
>Bar : Bar
myFunc<T extends Bar>(arg: T) {}
>myFunc : <T extends Bar>(arg: T) => void
>T : T
>Bar : Bar
>arg : T
>T : T
}
const myVar: Foo = new Bar();
>myVar : Foo
>Foo : Foo
>new Bar() : Bar
>Bar : typeof Bar

View file

@ -138,7 +138,7 @@ function foo8(x) {
var b;
return typeof x === "string"
? x === "hello"
: ((b = x) &&
: ((b = x) &&// number | boolean
(typeof x === "boolean"
? x // boolean
: x == 10)); // boolean

View file

@ -0,0 +1,12 @@
var a = 'some'
// comment
+ 'text';
var b = 'some'
/* comment */
+ 'text';
var c = 'some'
/* comment */
+ /*comment1*/
'text';

View file

@ -0,0 +1,13 @@
// @removeComments: true
var a = 'some'
// comment
+ 'text';
var b = 'some'
/* comment */
+ 'text';
var c = 'some'
/* comment */
+ /*comment1*/
'text';

View file

@ -0,0 +1,28 @@
// @strict: true
// @declaration: true
// Repro from #17456
type StringContains<S extends string, L extends string> = (
{ [K in S]: 'true' } &
{ [key: string]: 'false' }
)[L]
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>
type First<T> = ObjectHasKey<T, '0'>; // Should be deferred
type T1 = ObjectHasKey<{ a: string }, 'a'>; // 'true'
type T2 = ObjectHasKey<{ a: string }, 'b'>; // 'false'
// Verify that mapped type isn't eagerly resolved in type-to-string operation
declare function f1<A extends string, B extends string>(a: A, b: B): { [P in A | B]: any };
function f2<A extends string>(a: A) {
return f1(a, 'x');
}
function f3(x: 'a' | 'b') {
return f2(x);
}

View file

@ -0,0 +1,24 @@
// @strict: true
// @declaration: true
// Repro from #17456
type StringContains<S extends string, L extends string> = ({ [K in S]: 'true' } & { [key: string]: 'false'})[L];
type ObjectHasKey<O, L extends string> = StringContains<keyof O, L>;
type A<T> = ObjectHasKey<T, '0'>;
type B = ObjectHasKey<[string, number], '1'>; // "true"
type C = ObjectHasKey<[string, number], '2'>; // "false"
type D = A<[string]>; // "true"
// Error, "false" not handled
type E<T> = { true: 'true' }[ObjectHasKey<T, '1'>];
type Juxtapose<T> = ({ true: 'otherwise' } & { [k: string]: 'true' })[ObjectHasKey<T, '1'>];
// Error, "otherwise" is missing
type DeepError<T> = { true: 'true' }[Juxtapose<T>];
type DeepOK<T> = { true: 'true', otherwise: 'false' }[Juxtapose<T>];

View file

@ -0,0 +1,6 @@
// #16709
declare function dearray<T>(ara: ReadonlyArray<T>): T;
type LiteralType = "foo" | "bar";
declare var alt: Array<LiteralType>;
let foo: LiteralType = dearray(alt);

View file

@ -0,0 +1,45 @@
// @Filename: base.d.ts
declare const x: "foo".charCodeAt(0);
// @filename: string.ts
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
}
}
const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));
// @filename: number.ts
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}
const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));
// @filename: boolean.ts
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
}
}
const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));

View file

@ -0,0 +1,35 @@
// @strict: true
// @declaration: true
// A mapped type { [P in K]: X }, where K is a generic type, is related to
// { [key: string]: Y } if X is related to Y.
function f1<T, K extends string>(x: { [key: string]: T }, y: Record<K, T>) {
x = y;
y = x; // Error
}
function f2<T>(x: { [key: string]: T }, y: Record<string, T>) {
x = y;
y = x;
}
function f3<T, U, K extends string>(x: { [key: string]: T }, y: Record<K, U>) {
x = y; // Error
y = x; // Error
}
// Repro from #14548
type Dictionary = {
[key: string]: string;
};
interface IBaseEntity {
name: string;
properties: Dictionary;
}
interface IEntity<T extends string> extends IBaseEntity {
properties: Record<T, string>;
}

View file

@ -0,0 +1,13 @@
// @strict: true
// Repro from #17148
class Foo {
myFunc<T extends Foo>(arg: T) {}
}
class Bar {
myFunc<T extends Bar>(arg: T) {}
}
const myVar: Foo = new Bar();

View file

@ -0,0 +1,9 @@
/// <reference path="fourslash.ts"/>
////const { b/**/ } = new class {
//// private ab;
//// protected bc;
////}
goTo.marker();
verify.completionListIsEmpty();