Merge branch 'master' into incrementalLateSymbol

This commit is contained in:
Sheetal Nandi
2019-04-17 15:41:53 -07:00
38 changed files with 1732 additions and 72 deletions
+1 -4
View File
@@ -236,10 +236,7 @@ namespace ts {
}
});
if (oldCompilerOptions &&
(oldCompilerOptions.outDir !== compilerOptions.outDir ||
oldCompilerOptions.declarationDir !== compilerOptions.declarationDir ||
(oldCompilerOptions.outFile || oldCompilerOptions.out) !== (compilerOptions.outFile || compilerOptions.out))) {
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
// Add all files to affectedFilesPendingEmit since emit changed
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, newProgram.getSourceFiles().map(f => f.path));
if (state.affectedFilesPendingEmitIndex === undefined) {
+66 -46
View File
@@ -114,6 +114,11 @@ namespace ts {
getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount,
getTypeCount: () => typeCount,
getRelationCacheSizes: () => ({
assignable: assignableRelation.size,
identity: identityRelation.size,
subtype: subtypeRelation.size,
}),
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
isUnknownSymbol: symbol => symbol === unknownSymbol,
@@ -7474,6 +7479,25 @@ namespace ts {
return type.resolvedProperties;
}
function getPossiblePropertiesOfUnionType(type: UnionType): Symbol[] {
if (type.possiblePropertyCache) {
return type.possiblePropertyCache.size ? arrayFrom(type.possiblePropertyCache.values()) : emptyArray;
}
type.possiblePropertyCache = createSymbolTable();
for (const t of type.types) {
for (const p of getPropertiesOfType(t)) {
if (!type.possiblePropertyCache.has(p.escapedName)) {
const prop = getUnionOrIntersectionProperty(type, p.escapedName);
if (prop) {
type.possiblePropertyCache.set(p.escapedName, prop);
}
}
}
}
// We can't simply use the normal property cache here, since that will contain cached apparent type members :(
return type.possiblePropertyCache.size ? arrayFrom(type.possiblePropertyCache.values()) : emptyArray;
}
function getPropertiesOfType(type: Type): Symbol[] {
type = getApparentType(type);
return type.flags & TypeFlags.UnionOrIntersection ?
@@ -7831,7 +7855,7 @@ namespace ts {
const isUnion = containingType.flags & TypeFlags.Union;
const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
// Flags we want to propagate to the result if they exist in all source symbols
let commonFlags = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
let optionalFlag = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
let syntheticFlag = CheckFlags.SyntheticMethod;
let checkFlags = 0;
for (const current of containingType.types) {
@@ -7840,7 +7864,12 @@ namespace ts {
const prop = getPropertyOfType(type, name);
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
if (prop && !(modifiers & excludeModifiers)) {
commonFlags &= prop.flags;
if (isUnion) {
optionalFlag |= (prop.flags & SymbolFlags.Optional);
}
else {
optionalFlag &= prop.flags;
}
const id = "" + getSymbolId(prop);
if (!propSet.has(id)) {
propSet.set(id, prop);
@@ -7858,10 +7887,11 @@ namespace ts {
const indexInfo = !isLateBoundName(name) && (isNumericLiteralName(name) && getIndexInfoOfType(type, IndexKind.Number) || getIndexInfoOfType(type, IndexKind.String));
if (indexInfo) {
checkFlags |= indexInfo.isReadonly ? CheckFlags.Readonly : 0;
checkFlags |= CheckFlags.WritePartial;
indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type);
}
else {
checkFlags |= CheckFlags.Partial;
checkFlags |= CheckFlags.ReadPartial;
}
}
}
@@ -7870,7 +7900,7 @@ namespace ts {
return undefined;
}
const props = arrayFrom(propSet.values());
if (props.length === 1 && !(checkFlags & CheckFlags.Partial) && !indexTypes) {
if (props.length === 1 && !(checkFlags & CheckFlags.ReadPartial) && !indexTypes) {
return props[0];
}
let declarations: Declaration[] | undefined;
@@ -7901,7 +7931,7 @@ namespace ts {
propTypes.push(type);
}
addRange(propTypes, indexTypes);
const result = createSymbol(SymbolFlags.Property | commonFlags, name, syntheticFlag | checkFlags);
const result = createSymbol(SymbolFlags.Property | optionalFlag, name, syntheticFlag | checkFlags);
result.containingType = containingType;
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
result.valueDeclaration = firstValueDeclaration;
@@ -7938,7 +7968,7 @@ namespace ts {
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String): Symbol | undefined {
const property = getUnionOrIntersectionProperty(type, name);
// We need to filter out partial properties in union types
return property && !(getCheckFlags(property) & CheckFlags.Partial) ? property : undefined;
return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined;
}
/**
@@ -12277,25 +12307,6 @@ namespace ts {
return true;
}
function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
return false;
}
// at this point we know that this is union or intersection type possibly with nullable constituents.
// check if we still will have compound type if we ignore nullable components.
let seenNonNullable = false;
for (const t of (<UnionOrIntersectionType>type).types) {
if (t.flags & TypeFlags.Nullable) {
continue;
}
if (seenNonNullable) {
return true;
}
seenNonNullable = true;
}
return false;
}
/**
* Compare two types and return
* * Ternary.True if they are related with no assumptions,
@@ -12350,7 +12361,8 @@ namespace ts {
isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
if (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral) {
const isPerformingExcessPropertyChecks = (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral);
if (isPerformingExcessPropertyChecks) {
const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
if (hasExcessProperties(<FreshObjectLiteralType>source, target, discriminantType, reportErrors)) {
if (reportErrors) {
@@ -12358,13 +12370,6 @@ namespace ts {
}
return Ternary.False;
}
// Above we check for excess properties with respect to the entire target type. When union
// and intersection types are further deconstructed on the target side, we don't want to
// make the check again (as it might fail for a partial target type). Therefore we obtain
// the regular source type and proceed with that.
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target) && !discriminantType) {
source = getRegularTypeOfObjectLiteral(source);
}
}
if (relation !== comparableRelation && !isApparentIntersectionConstituent &&
@@ -12400,11 +12405,24 @@ namespace ts {
}
else {
if (target.flags & TypeFlags.Union) {
result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
if (result && isPerformingExcessPropertyChecks) {
// Validate against excess props using the original `source`
const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
if (!propertiesRelatedTo(source, discriminantType || target, reportErrors)) {
return Ternary.False;
}
}
}
else if (target.flags & TypeFlags.Intersection) {
isIntersectionConstituent = true; // set here to affect the following trio of checks
result = typeRelatedToEachType(source, target as IntersectionType, reportErrors);
result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors);
if (result && isPerformingExcessPropertyChecks) {
// Validate against excess props using the original `source`
if (!propertiesRelatedTo(source, target, reportErrors)) {
return Ternary.False;
}
}
}
else if (source.flags & TypeFlags.Intersection) {
// Check to see if any constituents of the intersection are immediately related to the target.
@@ -12507,7 +12525,7 @@ namespace ts {
// check excess properties against discriminant type only, not the entire union
return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors);
}
for (const prop of getPropertiesOfObjectType(source)) {
for (const prop of getPropertiesOfType(source)) {
if (shouldCheckAsExcessProperty(prop, source.symbol) && !isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
if (reportErrors) {
// Report error in terms of object types in the target as those are the only ones
@@ -13234,7 +13252,9 @@ namespace ts {
}
}
}
const properties = getPropertiesOfObjectType(target);
// We only call this for union target types when we're attempting to do excess property checking - in those cases, we want to get _all possible props_
// from the target union, across all members
const properties = target.flags & TypeFlags.Union ? getPossiblePropertiesOfUnionType(target as UnionType) : getPropertiesOfType(target);
for (const targetProp of properties) {
if (!(targetProp.flags & SymbolFlags.Prototype)) {
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
@@ -13282,7 +13302,8 @@ namespace ts {
}
return Ternary.False;
}
const related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
// If the target comes from a partial union prop, allow `undefined` in the target type
const related = isRelatedTo(getTypeOfSymbol(sourceProp), addOptionality(getTypeOfSymbol(targetProp), !!(getCheckFlags(targetProp) & CheckFlags.Partial)), reportErrors);
if (!related) {
if (reportErrors) {
reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
@@ -14628,9 +14649,9 @@ namespace ts {
}
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean) {
const properties = target.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(<IntersectionType>target) : getPropertiesOfObjectType(target);
const properties = target.flags & TypeFlags.Union ? getPossiblePropertiesOfUnionType(target as UnionType) : getPropertiesOfType(target);
for (const targetProp of properties) {
if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional)) {
if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) {
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
if (!sourceProp) {
yield targetProp;
@@ -15001,12 +15022,11 @@ namespace ts {
}
// If no inferences can be made to K's constraint, infer from a union of the property types
// in the source to the template type X.
const valueTypes = compact([
getIndexTypeOfType(source, IndexKind.String),
getIndexTypeOfType(source, IndexKind.Number),
...map(getPropertiesOfType(source), getTypeOfSymbol)
]);
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(target));
const propTypes = map(getPropertiesOfType(source), getTypeOfSymbol);
const stringIndexType = getIndexTypeOfType(source, IndexKind.String);
const numberIndexInfo = getNonEnumNumberIndexInfo(source);
const numberIndexType = numberIndexInfo && numberIndexInfo.type;
inferFromTypes(getUnionType(append(append(propTypes, stringIndexType), numberIndexType)), getTemplateTypeFromMappedType(target));
return true;
}
return false;
+30
View File
@@ -281,6 +281,7 @@ namespace ts {
name: "declaration",
shortName: "d",
type: "boolean",
affectsEmit: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Generates_corresponding_d_ts_file,
@@ -288,6 +289,7 @@ namespace ts {
{
name: "declarationMap",
type: "boolean",
affectsEmit: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Generates_a_sourcemap_for_each_corresponding_d_ts_file,
@@ -295,12 +297,14 @@ namespace ts {
{
name: "emitDeclarationOnly",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Only_emit_d_ts_declaration_files,
},
{
name: "sourceMap",
type: "boolean",
affectsEmit: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Generates_corresponding_map_file,
@@ -308,6 +312,7 @@ namespace ts {
{
name: "outFile",
type: "string",
affectsEmit: true,
isFilePath: true,
paramType: Diagnostics.FILE,
showInSimplifiedHelpView: true,
@@ -317,6 +322,7 @@ namespace ts {
{
name: "outDir",
type: "string",
affectsEmit: true,
isFilePath: true,
paramType: Diagnostics.DIRECTORY,
showInSimplifiedHelpView: true,
@@ -326,6 +332,7 @@ namespace ts {
{
name: "rootDir",
type: "string",
affectsEmit: true,
isFilePath: true,
paramType: Diagnostics.LOCATION,
category: Diagnostics.Basic_Options,
@@ -334,6 +341,7 @@ namespace ts {
{
name: "composite",
type: "boolean",
affectsEmit: true,
isTSConfigOnly: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Enable_project_compilation,
@@ -341,6 +349,7 @@ namespace ts {
{
name: "tsBuildInfoFile",
type: "string",
affectsEmit: true,
isFilePath: true,
paramType: Diagnostics.FILE,
category: Diagnostics.Basic_Options,
@@ -349,6 +358,7 @@ namespace ts {
{
name: "removeComments",
type: "boolean",
affectsEmit: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Do_not_emit_comments_to_output,
@@ -356,6 +366,7 @@ namespace ts {
{
name: "noEmit",
type: "boolean",
affectsEmit: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Do_not_emit_outputs,
@@ -363,12 +374,14 @@ namespace ts {
{
name: "importHelpers",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Import_emit_helpers_from_tslib
},
{
name: "downlevelIteration",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Provide_full_support_for_iterables_in_for_of_spread_and_destructuring_when_targeting_ES5_or_ES3
},
@@ -580,6 +593,7 @@ namespace ts {
{
name: "sourceRoot",
type: "string",
affectsEmit: true,
paramType: Diagnostics.LOCATION,
category: Diagnostics.Source_Map_Options,
description: Diagnostics.Specify_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
@@ -587,6 +601,7 @@ namespace ts {
{
name: "mapRoot",
type: "string",
affectsEmit: true,
paramType: Diagnostics.LOCATION,
category: Diagnostics.Source_Map_Options,
description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
@@ -594,12 +609,14 @@ namespace ts {
{
name: "inlineSourceMap",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Source_Map_Options,
description: Diagnostics.Emit_a_single_file_with_source_maps_instead_of_having_a_separate_file
},
{
name: "inlineSources",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Source_Map_Options,
description: Diagnostics.Emit_the_source_alongside_the_sourcemaps_within_a_single_file_requires_inlineSourceMap_or_sourceMap_to_be_set
},
@@ -635,6 +652,7 @@ namespace ts {
{
name: "out",
type: "string",
affectsEmit: true,
isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files
// for correct behaviour, please use outFile
category: Diagnostics.Advanced_Options,
@@ -644,6 +662,7 @@ namespace ts {
{
name: "reactNamespace",
type: "string",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Deprecated_Use_jsxFactory_instead_Specify_the_object_invoked_for_createElement_when_targeting_react_JSX_emit
},
@@ -662,6 +681,7 @@ namespace ts {
{
name: "emitBOM",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Emit_a_UTF_8_Byte_Order_Mark_BOM_in_the_beginning_of_output_files
},
@@ -677,6 +697,7 @@ namespace ts {
crlf: NewLineKind.CarriageReturnLineFeed,
lf: NewLineKind.LineFeed
}),
affectsEmit: true,
paramType: Diagnostics.NEWLINE,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix,
@@ -704,6 +725,7 @@ namespace ts {
{
name: "stripInternal",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
},
@@ -724,24 +746,28 @@ namespace ts {
{
name: "noEmitHelpers",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Do_not_generate_custom_helper_functions_like_extends_in_compiled_output
},
{
name: "noEmitOnError",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
},
{
name: "preserveConstEnums",
type: "boolean",
affectsEmit: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
},
{
name: "declarationDir",
type: "string",
affectsEmit: true,
isFilePath: true,
paramType: Diagnostics.DIRECTORY,
category: Diagnostics.Advanced_Options,
@@ -826,6 +852,10 @@ namespace ts {
export const semanticDiagnosticsOptionDeclarations: ReadonlyArray<CommandLineOption> =
optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics);
/* @internal */
export const affectsEmitOptionDeclarations: ReadonlyArray<CommandLineOption> =
optionDeclarations.filter(option => !!option.affectsEmit);
/* @internal */
export const moduleResolutionOptionDeclarations: ReadonlyArray<CommandLineOption> =
optionDeclarations.filter(option => !!option.affectsModuleResolution);
+1
View File
@@ -927,6 +927,7 @@ namespace ts {
getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(),
getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(),
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
getRelationCacheSizes: () => getDiagnosticsProducingTypeChecker().getRelationCacheSizes(),
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
isSourceFileFromExternalLibrary,
+19 -12
View File
@@ -2961,6 +2961,7 @@ namespace ts {
/* @internal */ getIdentifierCount(): number;
/* @internal */ getSymbolCount(): number;
/* @internal */ getTypeCount(): number;
/* @internal */ getRelationCacheSizes(): { assignable: number, identity: number, subtype: number };
/* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection;
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective | undefined>;
@@ -3246,6 +3247,7 @@ namespace ts {
/* @internal */ getIdentifierCount(): number;
/* @internal */ getSymbolCount(): number;
/* @internal */ getTypeCount(): number;
/* @internal */ getRelationCacheSizes(): { assignable: number, identity: number, subtype: number };
/* @internal */ isArrayType(type: Type): boolean;
/* @internal */ isTupleType(type: Type): boolean;
@@ -3746,19 +3748,21 @@ namespace ts {
SyntheticProperty = 1 << 1, // Property in union or intersection type
SyntheticMethod = 1 << 2, // Method in union or intersection type
Readonly = 1 << 3, // Readonly transient symbol
Partial = 1 << 4, // Synthetic property present in some but not all constituents
HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents
HasLiteralType = 1 << 6, // Synthetic property with at least one literal type in constituents
ContainsPublic = 1 << 7, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 8, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 9, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 10, // Synthetic property with static constituent(s)
Late = 1 << 11, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 12, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 13, // Optional parameter
RestParameter = 1 << 14, // Rest parameter
ReadPartial = 1 << 4, // Synthetic property present in some but not all constituents
WritePartial = 1 << 5, // Synthetic property present in some but only satisfied by an index signature in others
HasNonUniformType = 1 << 6, // Synthetic property with non-uniform type in constituents
HasLiteralType = 1 << 7, // Synthetic property with at least one literal type in constituents
ContainsPublic = 1 << 8, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 9, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 10, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 11, // Synthetic property with static constituent(s)
Late = 1 << 12, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 13, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 14, // Optional parameter
RestParameter = 1 << 15, // Rest parameter
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType
Discriminant = HasNonUniformType | HasLiteralType,
Partial = ReadPartial | WritePartial
}
/* @internal */
@@ -4171,6 +4175,8 @@ namespace ts {
}
export interface UnionType extends UnionOrIntersectionType {
/* @internal */
possiblePropertyCache?: SymbolTable; // Cache of _all_ resolved properties less any from aparent members
}
export interface IntersectionType extends UnionOrIntersectionType {
@@ -4823,6 +4829,7 @@ namespace ts {
affectsModuleResolution?: true; // currently same effect as `affectsSourceFile`
affectsBindDiagnostics?: true; // true if this affects binding (currently same effect as `affectsSourceFile`)
affectsSemanticDiagnostics?: true; // true if option affects semantic diagnostics
affectsEmit?: true; // true if the options affects emit
}
/* @internal */
+5
View File
@@ -7320,6 +7320,11 @@ namespace ts {
semanticDiagnosticsOptionDeclarations.some(option => !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option)));
}
export function compilerOptionsAffectEmit(newOptions: CompilerOptions, oldOptions: CompilerOptions): boolean {
return oldOptions !== newOptions &&
affectsEmitOptionDeclarations.some(option => !isJsonEqual(getCompilerOptionValue(oldOptions, option), getCompilerOptionValue(newOptions, option)));
}
export function getCompilerOptionValue(options: CompilerOptions, option: CommandLineOption): unknown {
return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name];
}
@@ -720,6 +720,47 @@ class someClass { }`),
"/src/tests/tsconfig.tsbuildinfo",
]
});
verifyTsbuildOutput({
scenario: "when declaration option changes",
projFs: () => projFs,
time,
tick,
proj: "sample1",
rootNames: ["/src/core"],
expectedMapFileNames: emptyArray,
lastProjectOutputJs: "/src/core/index.js",
initialBuild: {
modifyFs: fs => fs.writeFileSync("/src/core/tsconfig.json", `{
"compilerOptions": {
"incremental": true,
"skipDefaultLibCheck": true
}
}`),
expectedDiagnostics: [
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
]
},
incrementalDtsChangedBuild: {
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`),
expectedDiagnostics: [
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json"),
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.d.ts"],
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"]
]
},
outputFiles: [
"/src/core/anotherModule.js",
"/src/core/anotherModule.d.ts",
"/src/core/index.js",
"/src/core/index.d.ts",
"/src/core/tsconfig.tsbuildinfo",
],
baselineOnly: true,
verifyDiagnostics: true
});
});
});
}
+4
View File
@@ -340,6 +340,10 @@ namespace ts {
const checkTime = performance.getDuration("Check");
const emitTime = performance.getDuration("Emit");
if (compilerOptions.extendedDiagnostics) {
const caches = program.getRelationCacheSizes();
reportCountStatistic("Assignability cache size", caches.assignable);
reportCountStatistic("Identity cache size", caches.identity);
reportCountStatistic("Subtype cache size", caches.subtype);
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
}
else {
@@ -0,0 +1,48 @@
tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(21,33): error TS2322: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'.
Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'.
tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts(27,34): error TS2326: Types of property 'icon' are incompatible.
Type '{ props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }' is not assignable to type 'NestedProp<ITestProps>'.
Types of property 'props' are incompatible.
Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'.
Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'.
==== tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts (2 errors) ====
interface StatelessComponent<P = {}> {
(props: P & { children?: number }, context?: any): null;
}
const TestComponent: StatelessComponent<TestProps> = (props) => {
return null;
}
interface ITestProps {
ariaLabel?: string;
}
interface NestedProp<TProps> {
props: TProps;
}
interface TestProps {
icon: NestedProp<ITestProps>;
}
TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'.
!!! error TS2322: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'.
!!! related TS6500 tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts:14:3: The expected type comes from property 'props' which is declared here on type 'NestedProp<ITestProps>'
const TestComponent2: StatelessComponent<TestProps | {props2: {x: number}}> = (props) => {
return null;
}
TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2326: Types of property 'icon' are incompatible.
!!! error TS2326: Type '{ props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }' is not assignable to type 'NestedProp<ITestProps>'.
!!! error TS2326: Types of property 'props' are incompatible.
!!! error TS2326: Type '{ INVALID_PROP_NAME: string; ariaLabel: string; }' is not assignable to type 'ITestProps'.
!!! error TS2326: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'ITestProps'.
@@ -0,0 +1,39 @@
//// [deepExcessPropertyCheckingWhenTargetIsIntersection.ts]
interface StatelessComponent<P = {}> {
(props: P & { children?: number }, context?: any): null;
}
const TestComponent: StatelessComponent<TestProps> = (props) => {
return null;
}
interface ITestProps {
ariaLabel?: string;
}
interface NestedProp<TProps> {
props: TProps;
}
interface TestProps {
icon: NestedProp<ITestProps>;
}
TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
const TestComponent2: StatelessComponent<TestProps | {props2: {x: number}}> = (props) => {
return null;
}
TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
//// [deepExcessPropertyCheckingWhenTargetIsIntersection.js]
var TestComponent = function (props) {
return null;
};
TestComponent({ icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } } });
var TestComponent2 = function (props) {
return null;
};
TestComponent2({ icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } } });
@@ -0,0 +1,71 @@
=== tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts ===
interface StatelessComponent<P = {}> {
>StatelessComponent : Symbol(StatelessComponent, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 0, 0))
>P : Symbol(P, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 0, 29))
(props: P & { children?: number }, context?: any): null;
>props : Symbol(props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 1, 3))
>P : Symbol(P, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 0, 29))
>children : Symbol(children, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 1, 15))
>context : Symbol(context, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 1, 36))
}
const TestComponent: StatelessComponent<TestProps> = (props) => {
>TestComponent : Symbol(TestComponent, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 4, 5))
>StatelessComponent : Symbol(StatelessComponent, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 0, 0))
>TestProps : Symbol(TestProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 14, 1))
>props : Symbol(props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 4, 54))
return null;
}
interface ITestProps {
>ITestProps : Symbol(ITestProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 6, 1))
ariaLabel?: string;
>ariaLabel : Symbol(ITestProps.ariaLabel, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 8, 22))
}
interface NestedProp<TProps> {
>NestedProp : Symbol(NestedProp, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 10, 1))
>TProps : Symbol(TProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 12, 21))
props: TProps;
>props : Symbol(NestedProp.props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 12, 30))
>TProps : Symbol(TProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 12, 21))
}
interface TestProps {
>TestProps : Symbol(TestProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 14, 1))
icon: NestedProp<ITestProps>;
>icon : Symbol(TestProps.icon, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 16, 21))
>NestedProp : Symbol(NestedProp, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 10, 1))
>ITestProps : Symbol(ITestProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 6, 1))
}
TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
>TestComponent : Symbol(TestComponent, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 4, 5))
>icon : Symbol(icon, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 20, 15))
>props : Symbol(props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 20, 22))
>INVALID_PROP_NAME : Symbol(INVALID_PROP_NAME, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 20, 31))
>ariaLabel : Symbol(ariaLabel, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 20, 59))
const TestComponent2: StatelessComponent<TestProps | {props2: {x: number}}> = (props) => {
>TestComponent2 : Symbol(TestComponent2, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 22, 5))
>StatelessComponent : Symbol(StatelessComponent, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 0, 0))
>TestProps : Symbol(TestProps, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 14, 1))
>props2 : Symbol(props2, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 22, 54))
>x : Symbol(x, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 22, 63))
>props : Symbol(props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 22, 79))
return null;
}
TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
>TestComponent2 : Symbol(TestComponent2, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 22, 5))
>icon : Symbol(icon, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 26, 16))
>props : Symbol(props, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 26, 23))
>INVALID_PROP_NAME : Symbol(INVALID_PROP_NAME, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 26, 32))
>ariaLabel : Symbol(ariaLabel, Decl(deepExcessPropertyCheckingWhenTargetIsIntersection.ts, 26, 60))
@@ -0,0 +1,70 @@
=== tests/cases/compiler/deepExcessPropertyCheckingWhenTargetIsIntersection.ts ===
interface StatelessComponent<P = {}> {
(props: P & { children?: number }, context?: any): null;
>props : P & { children?: number; }
>children : number
>context : any
>null : null
}
const TestComponent: StatelessComponent<TestProps> = (props) => {
>TestComponent : StatelessComponent<TestProps>
>(props) => { return null;} : (props: TestProps & { children?: number; }) => any
>props : TestProps & { children?: number; }
return null;
>null : null
}
interface ITestProps {
ariaLabel?: string;
>ariaLabel : string
}
interface NestedProp<TProps> {
props: TProps;
>props : TProps
}
interface TestProps {
icon: NestedProp<ITestProps>;
>icon : NestedProp<ITestProps>
}
TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
>TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }}) : null
>TestComponent : StatelessComponent<TestProps>
>{icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }} : { icon: { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }; }
>icon : { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }
>{ props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } } : { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }
>props : { INVALID_PROP_NAME: string; ariaLabel: string; }
>{ INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } : { INVALID_PROP_NAME: string; ariaLabel: string; }
>INVALID_PROP_NAME : string
>'share' : "share"
>ariaLabel : string
>'test label' : "test label"
const TestComponent2: StatelessComponent<TestProps | {props2: {x: number}}> = (props) => {
>TestComponent2 : StatelessComponent<TestProps | { props2: { x: number; }; }>
>props2 : { x: number; }
>x : number
>(props) => { return null;} : (props: (TestProps & { children?: number; }) | ({ props2: { x: number; }; } & { children?: number; })) => any
>props : (TestProps & { children?: number; }) | ({ props2: { x: number; }; } & { children?: number; })
return null;
>null : null
}
TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
>TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }}) : null
>TestComponent2 : StatelessComponent<TestProps | { props2: { x: number; }; }>
>{icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }} : { icon: { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }; }
>icon : { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }
>{ props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } } : { props: { INVALID_PROP_NAME: string; ariaLabel: string; }; }
>props : { INVALID_PROP_NAME: string; ariaLabel: string; }
>{ INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } : { INVALID_PROP_NAME: string; ariaLabel: string; }
>INVALID_PROP_NAME : string
>'share' : "share"
>ariaLabel : string
>'test label' : "test label"
@@ -20,11 +20,9 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(49,35): error TS2322: Type
Object literal may only specify known properties, and 'second' does not exist in type '{ a: 1; b: 1; first: string; }'.
tests/cases/compiler/excessPropertyCheckWithUnions.ts(50,35): error TS2322: Type '{ a: 1; b: 1; first: string; third: string; }' is not assignable to type 'Overlapping'.
Object literal may only specify known properties, and 'third' does not exist in type '{ a: 1; b: 1; first: string; }'.
tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2322: Type '{ kind: "A"; n: { a: string; b: string; }; }' is not assignable to type 'AB'.
Type '{ kind: "A"; n: { a: string; b: string; }; }' is not assignable to type '{ kind: "A"; n: AN; }'.
Types of property 'n' are incompatible.
Type '{ a: string; b: string; }' is not assignable to type 'AN'.
Object literal may only specify known properties, and 'b' does not exist in type 'AN'.
tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2326: Types of property 'n' are incompatible.
Type '{ a: string; b: string; }' is not assignable to type 'AN'.
Object literal may only specify known properties, and 'b' does not exist in type 'AN'.
==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (10 errors) ====
@@ -127,11 +125,9 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2322: Type
a: "a",
b: "b", // excess -- kind: "A"
~~~~~~
!!! error TS2322: Type '{ kind: "A"; n: { a: string; b: string; }; }' is not assignable to type 'AB'.
!!! error TS2322: Type '{ kind: "A"; n: { a: string; b: string; }; }' is not assignable to type '{ kind: "A"; n: AN; }'.
!!! error TS2322: Types of property 'n' are incompatible.
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type 'AN'.
!!! error TS2322: Object literal may only specify known properties, and 'b' does not exist in type 'AN'.
!!! error TS2326: Types of property 'n' are incompatible.
!!! error TS2326: Type '{ a: string; b: string; }' is not assignable to type 'AN'.
!!! error TS2326: Object literal may only specify known properties, and 'b' does not exist in type 'AN'.
}
}
const abac: AB = {
@@ -0,0 +1,116 @@
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(18,19): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(19,31): error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'A'.
Object literal may only specify known properties, and 'y' does not exist in type 'A'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(22,19): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(23,31): error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'A'.
Object literal may only specify known properties, and 'y' does not exist in type 'A'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(34,5): error TS2322: Type '{ id: number; url: string; xyz: number; }' is not assignable to type '{ id: number; } & { url: string; }'.
Object literal may only specify known properties, and 'xyz' does not exist in type '{ id: number; } & { url: string; }'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(43,9): error TS2322: Type '{ id: number; url: string; xyz: number; }' is not assignable to type '{ id: number; } & { url: string; }'.
Object literal may only specify known properties, and 'xyz' does not exist in type '{ id: number; } & { url: string; }'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(68,32): error TS2322: Type '{ foo: true; bar: true; boo: boolean; }' is not assignable to type 'View<TypeA>'.
Object literal may only specify known properties, and 'boo' does not exist in type 'View<TypeA>'.
tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(70,50): error TS2322: Type '{ foo: true; bar: true; boo: boolean; }' is not assignable to type 'boolean | View<TypeB>'.
Object literal may only specify known properties, and 'boo' does not exist in type 'View<TypeB>'.
==== tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts (8 errors) ====
// https://github.com/Microsoft/TypeScript/issues/13813
interface A {
x: string
}
interface B {
a: A;
}
interface C {
c: number;
}
type D = B & C;
let a: B = { a: { x: 'hello' } }; // ok
let b: B = { a: { x: 2 } }; // error - types of property x are incompatible
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:4:5: The expected type comes from property 'x' which is declared here on type 'A'
let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
~~~~
!!! error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'A'.
!!! error TS2322: Object literal may only specify known properties, and 'y' does not exist in type 'A'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:8:5: The expected type comes from property 'a' which is declared here on type 'B'
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:4:5: The expected type comes from property 'x' which is declared here on type 'A'
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
~~~~
!!! error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'A'.
!!! error TS2322: Object literal may only specify known properties, and 'y' does not exist in type 'A'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:8:5: The expected type comes from property 'a' which is declared here on type 'D'
// https://github.com/Microsoft/TypeScript/issues/18075
export type MyType = { id: number; } & { name: string; } & { photo: { id: number; } & { url: string; } }
export let obj: MyType;
export const photo: typeof obj.photo = {
id: 1,
url: '',
xyz: 1 // Great! This causes an error!
~~~~~~
!!! error TS2322: Type '{ id: number; url: string; xyz: number; }' is not assignable to type '{ id: number; } & { url: string; }'.
!!! error TS2322: Object literal may only specify known properties, and 'xyz' does not exist in type '{ id: number; } & { url: string; }'.
};
export const myInstance: MyType = {
id: 1,
name: '',
photo: {
id: 1,
url: '',
xyz: 2 // This should also be an error
~~~~~~
!!! error TS2322: Type '{ id: number; url: string; xyz: number; }' is not assignable to type '{ id: number; } & { url: string; }'.
!!! error TS2322: Object literal may only specify known properties, and 'xyz' does not exist in type '{ id: number; } & { url: string; }'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:27:62: The expected type comes from property 'photo' which is declared here on type 'MyType'
}
};
// https://github.com/Microsoft/TypeScript/issues/28616
export type View<T> = { [K in keyof T]: T[K] extends object ? boolean | View<T[K]> : boolean };
interface TypeC {
foo: string;
bar: string;
}
interface TypeB {
foo: string,
bar: TypeC
}
interface TypeA {
foo: string,
bar: TypeB,
}
let test: View<TypeA>;
test = { foo: true, bar: true, boo: true }
~~~~~~~~~
!!! error TS2322: Type '{ foo: true; bar: true; boo: boolean; }' is not assignable to type 'View<TypeA>'.
!!! error TS2322: Object literal may only specify known properties, and 'boo' does not exist in type 'View<TypeA>'.
test = { foo: true, bar: { foo: true, bar: true, boo: true } }
~~~~~~~~~
!!! error TS2322: Type '{ foo: true; bar: true; boo: boolean; }' is not assignable to type 'boolean | View<TypeB>'.
!!! error TS2322: Object literal may only specify known properties, and 'boo' does not exist in type 'View<TypeB>'.
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:63:5: The expected type comes from property 'bar' which is declared here on type 'View<TypeA>'
@@ -0,0 +1,100 @@
//// [excessPropertyChecksWithNestedIntersections.ts]
// https://github.com/Microsoft/TypeScript/issues/13813
interface A {
x: string
}
interface B {
a: A;
}
interface C {
c: number;
}
type D = B & C;
let a: B = { a: { x: 'hello' } }; // ok
let b: B = { a: { x: 2 } }; // error - types of property x are incompatible
let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
// https://github.com/Microsoft/TypeScript/issues/18075
export type MyType = { id: number; } & { name: string; } & { photo: { id: number; } & { url: string; } }
export let obj: MyType;
export const photo: typeof obj.photo = {
id: 1,
url: '',
xyz: 1 // Great! This causes an error!
};
export const myInstance: MyType = {
id: 1,
name: '',
photo: {
id: 1,
url: '',
xyz: 2 // This should also be an error
}
};
// https://github.com/Microsoft/TypeScript/issues/28616
export type View<T> = { [K in keyof T]: T[K] extends object ? boolean | View<T[K]> : boolean };
interface TypeC {
foo: string;
bar: string;
}
interface TypeB {
foo: string,
bar: TypeC
}
interface TypeA {
foo: string,
bar: TypeB,
}
let test: View<TypeA>;
test = { foo: true, bar: true, boo: true }
test = { foo: true, bar: { foo: true, bar: true, boo: true } }
//// [excessPropertyChecksWithNestedIntersections.js]
"use strict";
// https://github.com/Microsoft/TypeScript/issues/13813
exports.__esModule = true;
var a = { a: { x: 'hello' } }; // ok
var b = { a: { x: 2 } }; // error - types of property x are incompatible
var c = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
var d = { a: { x: 'hello' }, c: 5 }; // ok
var e = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
var f = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
exports.photo = {
id: 1,
url: '',
xyz: 1 // Great! This causes an error!
};
exports.myInstance = {
id: 1,
name: '',
photo: {
id: 1,
url: '',
xyz: 2 // This should also be an error
}
};
var test;
test = { foo: true, bar: true, boo: true };
test = { foo: true, bar: { foo: true, bar: true, boo: true } };
@@ -0,0 +1,190 @@
=== tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts ===
// https://github.com/Microsoft/TypeScript/issues/13813
interface A {
>A : Symbol(A, Decl(excessPropertyChecksWithNestedIntersections.ts, 0, 0))
x: string
>x : Symbol(A.x, Decl(excessPropertyChecksWithNestedIntersections.ts, 2, 13))
}
interface B {
>B : Symbol(B, Decl(excessPropertyChecksWithNestedIntersections.ts, 4, 1))
a: A;
>a : Symbol(B.a, Decl(excessPropertyChecksWithNestedIntersections.ts, 6, 13))
>A : Symbol(A, Decl(excessPropertyChecksWithNestedIntersections.ts, 0, 0))
}
interface C {
>C : Symbol(C, Decl(excessPropertyChecksWithNestedIntersections.ts, 8, 1))
c: number;
>c : Symbol(C.c, Decl(excessPropertyChecksWithNestedIntersections.ts, 10, 13))
}
type D = B & C;
>D : Symbol(D, Decl(excessPropertyChecksWithNestedIntersections.ts, 12, 1))
>B : Symbol(B, Decl(excessPropertyChecksWithNestedIntersections.ts, 4, 1))
>C : Symbol(C, Decl(excessPropertyChecksWithNestedIntersections.ts, 8, 1))
let a: B = { a: { x: 'hello' } }; // ok
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 16, 3))
>B : Symbol(B, Decl(excessPropertyChecksWithNestedIntersections.ts, 4, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 16, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 16, 17))
let b: B = { a: { x: 2 } }; // error - types of property x are incompatible
>b : Symbol(b, Decl(excessPropertyChecksWithNestedIntersections.ts, 17, 3))
>B : Symbol(B, Decl(excessPropertyChecksWithNestedIntersections.ts, 4, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 17, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 17, 17))
let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
>c : Symbol(c, Decl(excessPropertyChecksWithNestedIntersections.ts, 18, 3))
>B : Symbol(B, Decl(excessPropertyChecksWithNestedIntersections.ts, 4, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 18, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 18, 17))
>y : Symbol(y, Decl(excessPropertyChecksWithNestedIntersections.ts, 18, 29))
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
>d : Symbol(d, Decl(excessPropertyChecksWithNestedIntersections.ts, 20, 3))
>D : Symbol(D, Decl(excessPropertyChecksWithNestedIntersections.ts, 12, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 20, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 20, 17))
>c : Symbol(c, Decl(excessPropertyChecksWithNestedIntersections.ts, 20, 31))
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
>e : Symbol(e, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 3))
>D : Symbol(D, Decl(excessPropertyChecksWithNestedIntersections.ts, 12, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 17))
>c : Symbol(c, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 25))
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
>f : Symbol(f, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 3))
>D : Symbol(D, Decl(excessPropertyChecksWithNestedIntersections.ts, 12, 1))
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 12))
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 17))
>y : Symbol(y, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 29))
>c : Symbol(c, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 37))
// https://github.com/Microsoft/TypeScript/issues/18075
export type MyType = { id: number; } & { name: string; } & { photo: { id: number; } & { url: string; } }
>MyType : Symbol(MyType, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 45))
>id : Symbol(id, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 22))
>name : Symbol(name, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 40))
>photo : Symbol(photo, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 60))
>id : Symbol(id, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 69))
>url : Symbol(url, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 87))
export let obj: MyType;
>obj : Symbol(obj, Decl(excessPropertyChecksWithNestedIntersections.ts, 28, 10))
>MyType : Symbol(MyType, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 45))
export const photo: typeof obj.photo = {
>photo : Symbol(photo, Decl(excessPropertyChecksWithNestedIntersections.ts, 30, 12))
>obj.photo : Symbol(photo, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 60))
>obj : Symbol(obj, Decl(excessPropertyChecksWithNestedIntersections.ts, 28, 10))
>photo : Symbol(photo, Decl(excessPropertyChecksWithNestedIntersections.ts, 26, 60))
id: 1,
>id : Symbol(id, Decl(excessPropertyChecksWithNestedIntersections.ts, 30, 40))
url: '',
>url : Symbol(url, Decl(excessPropertyChecksWithNestedIntersections.ts, 31, 10))
xyz: 1 // Great! This causes an error!
>xyz : Symbol(xyz, Decl(excessPropertyChecksWithNestedIntersections.ts, 32, 12))
};
export const myInstance: MyType = {
>myInstance : Symbol(myInstance, Decl(excessPropertyChecksWithNestedIntersections.ts, 36, 12))
>MyType : Symbol(MyType, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 45))
id: 1,
>id : Symbol(id, Decl(excessPropertyChecksWithNestedIntersections.ts, 36, 35))
name: '',
>name : Symbol(name, Decl(excessPropertyChecksWithNestedIntersections.ts, 37, 10))
photo: {
>photo : Symbol(photo, Decl(excessPropertyChecksWithNestedIntersections.ts, 38, 13))
id: 1,
>id : Symbol(id, Decl(excessPropertyChecksWithNestedIntersections.ts, 39, 12))
url: '',
>url : Symbol(url, Decl(excessPropertyChecksWithNestedIntersections.ts, 40, 14))
xyz: 2 // This should also be an error
>xyz : Symbol(xyz, Decl(excessPropertyChecksWithNestedIntersections.ts, 41, 16))
}
};
// https://github.com/Microsoft/TypeScript/issues/28616
export type View<T> = { [K in keyof T]: T[K] extends object ? boolean | View<T[K]> : boolean };
>View : Symbol(View, Decl(excessPropertyChecksWithNestedIntersections.ts, 44, 2))
>T : Symbol(T, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 17))
>K : Symbol(K, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 25))
>T : Symbol(T, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 17))
>T : Symbol(T, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 17))
>K : Symbol(K, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 25))
>View : Symbol(View, Decl(excessPropertyChecksWithNestedIntersections.ts, 44, 2))
>T : Symbol(T, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 17))
>K : Symbol(K, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 25))
interface TypeC {
>TypeC : Symbol(TypeC, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 95))
foo: string;
>foo : Symbol(TypeC.foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 50, 17))
bar: string;
>bar : Symbol(TypeC.bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 51, 16))
}
interface TypeB {
>TypeB : Symbol(TypeB, Decl(excessPropertyChecksWithNestedIntersections.ts, 53, 1))
foo: string,
>foo : Symbol(TypeB.foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 55, 17))
bar: TypeC
>bar : Symbol(TypeB.bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 56, 16))
>TypeC : Symbol(TypeC, Decl(excessPropertyChecksWithNestedIntersections.ts, 48, 95))
}
interface TypeA {
>TypeA : Symbol(TypeA, Decl(excessPropertyChecksWithNestedIntersections.ts, 58, 1))
foo: string,
>foo : Symbol(TypeA.foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 60, 17))
bar: TypeB,
>bar : Symbol(TypeA.bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 61, 16))
>TypeB : Symbol(TypeB, Decl(excessPropertyChecksWithNestedIntersections.ts, 53, 1))
}
let test: View<TypeA>;
>test : Symbol(test, Decl(excessPropertyChecksWithNestedIntersections.ts, 65, 3))
>View : Symbol(View, Decl(excessPropertyChecksWithNestedIntersections.ts, 44, 2))
>TypeA : Symbol(TypeA, Decl(excessPropertyChecksWithNestedIntersections.ts, 58, 1))
test = { foo: true, bar: true, boo: true }
>test : Symbol(test, Decl(excessPropertyChecksWithNestedIntersections.ts, 65, 3))
>foo : Symbol(foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 67, 8))
>bar : Symbol(bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 67, 19))
>boo : Symbol(boo, Decl(excessPropertyChecksWithNestedIntersections.ts, 67, 30))
test = { foo: true, bar: { foo: true, bar: true, boo: true } }
>test : Symbol(test, Decl(excessPropertyChecksWithNestedIntersections.ts, 65, 3))
>foo : Symbol(foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 69, 8))
>bar : Symbol(bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 69, 19))
>foo : Symbol(foo, Decl(excessPropertyChecksWithNestedIntersections.ts, 69, 26))
>bar : Symbol(bar, Decl(excessPropertyChecksWithNestedIntersections.ts, 69, 37))
>boo : Symbol(boo, Decl(excessPropertyChecksWithNestedIntersections.ts, 69, 48))
@@ -0,0 +1,201 @@
=== tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts ===
// https://github.com/Microsoft/TypeScript/issues/13813
interface A {
x: string
>x : string
}
interface B {
a: A;
>a : A
}
interface C {
c: number;
>c : number
}
type D = B & C;
>D : D
let a: B = { a: { x: 'hello' } }; // ok
>a : B
>{ a: { x: 'hello' } } : { a: { x: string; }; }
>a : { x: string; }
>{ x: 'hello' } : { x: string; }
>x : string
>'hello' : "hello"
let b: B = { a: { x: 2 } }; // error - types of property x are incompatible
>b : B
>{ a: { x: 2 } } : { a: { x: number; }; }
>a : { x: number; }
>{ x: 2 } : { x: number; }
>x : number
>2 : 2
let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
>c : B
>{ a: { x: 'hello', y: 2 } } : { a: { x: string; y: number; }; }
>a : { x: string; y: number; }
>{ x: 'hello', y: 2 } : { x: string; y: number; }
>x : string
>'hello' : "hello"
>y : number
>2 : 2
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
>d : D
>{ a: { x: 'hello' }, c: 5 } : { a: { x: string; }; c: number; }
>a : { x: string; }
>{ x: 'hello' } : { x: string; }
>x : string
>'hello' : "hello"
>c : number
>5 : 5
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
>e : D
>{ a: { x: 2 }, c: 5 } : { a: { x: number; }; c: number; }
>a : { x: number; }
>{ x: 2 } : { x: number; }
>x : number
>2 : 2
>c : number
>5 : 5
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
>f : D
>{ a: { x: 'hello', y: 2 }, c: 5 } : { a: { x: string; y: number; }; c: number; }
>a : { x: string; y: number; }
>{ x: 'hello', y: 2 } : { x: string; y: number; }
>x : string
>'hello' : "hello"
>y : number
>2 : 2
>c : number
>5 : 5
// https://github.com/Microsoft/TypeScript/issues/18075
export type MyType = { id: number; } & { name: string; } & { photo: { id: number; } & { url: string; } }
>MyType : MyType
>id : number
>name : string
>photo : { id: number; } & { url: string; }
>id : number
>url : string
export let obj: MyType;
>obj : MyType
export const photo: typeof obj.photo = {
>photo : { id: number; } & { url: string; }
>obj.photo : { id: number; } & { url: string; }
>obj : MyType
>photo : { id: number; } & { url: string; }
>{ id: 1, url: '', xyz: 1 // Great! This causes an error!} : { id: number; url: string; xyz: number; }
id: 1,
>id : number
>1 : 1
url: '',
>url : string
>'' : ""
xyz: 1 // Great! This causes an error!
>xyz : number
>1 : 1
};
export const myInstance: MyType = {
>myInstance : MyType
>{ id: 1, name: '', photo: { id: 1, url: '', xyz: 2 // This should also be an error }} : { id: number; name: string; photo: { id: number; url: string; xyz: number; }; }
id: 1,
>id : number
>1 : 1
name: '',
>name : string
>'' : ""
photo: {
>photo : { id: number; url: string; xyz: number; }
>{ id: 1, url: '', xyz: 2 // This should also be an error } : { id: number; url: string; xyz: number; }
id: 1,
>id : number
>1 : 1
url: '',
>url : string
>'' : ""
xyz: 2 // This should also be an error
>xyz : number
>2 : 2
}
};
// https://github.com/Microsoft/TypeScript/issues/28616
export type View<T> = { [K in keyof T]: T[K] extends object ? boolean | View<T[K]> : boolean };
>View : View<T>
interface TypeC {
foo: string;
>foo : string
bar: string;
>bar : string
}
interface TypeB {
foo: string,
>foo : string
bar: TypeC
>bar : TypeC
}
interface TypeA {
foo: string,
>foo : string
bar: TypeB,
>bar : TypeB
}
let test: View<TypeA>;
>test : View<TypeA>
test = { foo: true, bar: true, boo: true }
>test = { foo: true, bar: true, boo: true } : { foo: true; bar: true; boo: boolean; }
>test : View<TypeA>
>{ foo: true, bar: true, boo: true } : { foo: true; bar: true; boo: boolean; }
>foo : true
>true : true
>bar : true
>true : true
>boo : boolean
>true : true
test = { foo: true, bar: { foo: true, bar: true, boo: true } }
>test = { foo: true, bar: { foo: true, bar: true, boo: true } } : { foo: true; bar: { foo: true; bar: true; boo: boolean; }; }
>test : View<TypeA>
>{ foo: true, bar: { foo: true, bar: true, boo: true } } : { foo: true; bar: { foo: true; bar: true; boo: boolean; }; }
>foo : true
>true : true
>bar : { foo: true; bar: true; boo: boolean; }
>{ foo: true, bar: true, boo: true } : { foo: true; bar: true; boo: boolean; }
>foo : true
>true : true
>bar : true
>true : true
>boo : boolean
>true : true
@@ -2,7 +2,21 @@
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
declare const a: { [index: string]: number };
fn(a);
// Repro from #30218
declare function enumValues<K extends string, V extends string>(e: Record<K, V>): V[];
enum E { A = 'foo', B = 'bar' }
let x: E[] = enumValues(E);
//// [mappedToToIndexSignatureInference.js]
fn(a);
var E;
(function (E) {
E["A"] = "foo";
E["B"] = "bar";
})(E || (E = {}));
var x = enumValues(E);
@@ -16,3 +16,26 @@ fn(a);
>fn : Symbol(fn, Decl(mappedToToIndexSignatureInference.ts, 0, 13))
>a : Symbol(a, Decl(mappedToToIndexSignatureInference.ts, 1, 13))
// Repro from #30218
declare function enumValues<K extends string, V extends string>(e: Record<K, V>): V[];
>enumValues : Symbol(enumValues, Decl(mappedToToIndexSignatureInference.ts, 2, 6))
>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 6, 28))
>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 6, 45))
>e : Symbol(e, Decl(mappedToToIndexSignatureInference.ts, 6, 64))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
>K : Symbol(K, Decl(mappedToToIndexSignatureInference.ts, 6, 28))
>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 6, 45))
>V : Symbol(V, Decl(mappedToToIndexSignatureInference.ts, 6, 45))
enum E { A = 'foo', B = 'bar' }
>E : Symbol(E, Decl(mappedToToIndexSignatureInference.ts, 6, 86))
>A : Symbol(E.A, Decl(mappedToToIndexSignatureInference.ts, 8, 8))
>B : Symbol(E.B, Decl(mappedToToIndexSignatureInference.ts, 8, 19))
let x: E[] = enumValues(E);
>x : Symbol(x, Decl(mappedToToIndexSignatureInference.ts, 10, 3))
>E : Symbol(E, Decl(mappedToToIndexSignatureInference.ts, 6, 86))
>enumValues : Symbol(enumValues, Decl(mappedToToIndexSignatureInference.ts, 2, 6))
>E : Symbol(E, Decl(mappedToToIndexSignatureInference.ts, 6, 86))
@@ -12,3 +12,22 @@ fn(a);
>fn : <K extends string, V>(object: { [Key in K]: V; }) => object
>a : { [index: string]: number; }
// Repro from #30218
declare function enumValues<K extends string, V extends string>(e: Record<K, V>): V[];
>enumValues : <K extends string, V extends string>(e: Record<K, V>) => V[]
>e : Record<K, V>
enum E { A = 'foo', B = 'bar' }
>E : E
>A : E.A
>'foo' : "foo"
>B : E.B
>'bar' : "bar"
let x: E[] = enumValues(E);
>x : E[]
>enumValues(E) : E[]
>enumValues : <K extends string, V extends string>(e: Record<K, V>) => V[]
>E : typeof E
@@ -0,0 +1,44 @@
tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(13,35): error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'number | IProps'.
Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'.
tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(16,7): error TS2322: Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'number | IProps'.
Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'IProps'.
Types of property 'nestedProp' are incompatible.
Type '{ asdfasdf: string; }' has no properties in common with type '{ testBool?: boolean; }'.
tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts(19,56): error TS2326: Types of property 'nestedProps' are incompatible.
Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'.
Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'.
==== tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts (3 errors) ====
interface IProps {
iconProp?: string;
nestedProp?: {
testBool?: boolean;
}
}
interface INestedProps {
nestedProps?: IProps;
}
// These are the types of errors we want:
const propB1: IProps | number = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'number | IProps'.
!!! error TS2322: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'.
// Nested typing works here and we also get an expected error:
const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
~~~~~~
!!! error TS2322: Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'number | IProps'.
!!! error TS2322: Type '{ nestedProp: { asdfasdf: string; }; iconProp: string; }' is not assignable to type 'IProps'.
!!! error TS2322: Types of property 'nestedProp' are incompatible.
!!! error TS2322: Type '{ asdfasdf: string; }' has no properties in common with type '{ testBool?: boolean; }'.
// Want an error generated here but there isn't one.
const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2326: Types of property 'nestedProps' are incompatible.
!!! error TS2326: Type '{ INVALID_PROP_NAME: string; iconProp: string; }' is not assignable to type 'IProps'.
!!! error TS2326: Object literal may only specify known properties, and 'INVALID_PROP_NAME' does not exist in type 'IProps'.
@@ -0,0 +1,29 @@
//// [nonObjectUnionNestedExcessPropertyCheck.ts]
interface IProps {
iconProp?: string;
nestedProp?: {
testBool?: boolean;
}
}
interface INestedProps {
nestedProps?: IProps;
}
// These are the types of errors we want:
const propB1: IProps | number = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
// Nested typing works here and we also get an expected error:
const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
// Want an error generated here but there isn't one.
const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
//// [nonObjectUnionNestedExcessPropertyCheck.js]
// These are the types of errors we want:
var propB1 = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
// Nested typing works here and we also get an expected error:
var propB2 = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
// Want an error generated here but there isn't one.
var propA1 = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
@@ -0,0 +1,46 @@
=== tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts ===
interface IProps {
>IProps : Symbol(IProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 0, 0))
iconProp?: string;
>iconProp : Symbol(IProps.iconProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 0, 18))
nestedProp?: {
>nestedProp : Symbol(IProps.nestedProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 1, 22))
testBool?: boolean;
>testBool : Symbol(testBool, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 2, 18))
}
}
interface INestedProps {
>INestedProps : Symbol(INestedProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 5, 1))
nestedProps?: IProps;
>nestedProps : Symbol(INestedProps.nestedProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 7, 24))
>IProps : Symbol(IProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 0, 0))
}
// These are the types of errors we want:
const propB1: IProps | number = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
>propB1 : Symbol(propB1, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 12, 5))
>IProps : Symbol(IProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 0, 0))
>INVALID_PROP_NAME : Symbol(INVALID_PROP_NAME, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 12, 33))
>iconProp : Symbol(iconProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 12, 61))
// Nested typing works here and we also get an expected error:
const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
>propB2 : Symbol(propB2, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 15, 5))
>IProps : Symbol(IProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 0, 0))
>nestedProp : Symbol(nestedProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 15, 33))
>asdfasdf : Symbol(asdfasdf, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 15, 47))
>iconProp : Symbol(iconProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 15, 67))
// Want an error generated here but there isn't one.
const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
>propA1 : Symbol(propA1, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 18, 5))
>INestedProps : Symbol(INestedProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 5, 1))
>nestedProps : Symbol(nestedProps, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 18, 39))
>INVALID_PROP_NAME : Symbol(INVALID_PROP_NAME, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 18, 54))
>iconProp : Symbol(iconProp, Decl(nonObjectUnionNestedExcessPropertyCheck.ts, 18, 82))
@@ -0,0 +1,49 @@
=== tests/cases/compiler/nonObjectUnionNestedExcessPropertyCheck.ts ===
interface IProps {
iconProp?: string;
>iconProp : string
nestedProp?: {
>nestedProp : { testBool?: boolean; }
testBool?: boolean;
>testBool : boolean
}
}
interface INestedProps {
nestedProps?: IProps;
>nestedProps : IProps
}
// These are the types of errors we want:
const propB1: IProps | number = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
>propB1 : number | IProps
>{ INVALID_PROP_NAME: 'share', iconProp: 'test' } : { INVALID_PROP_NAME: string; iconProp: string; }
>INVALID_PROP_NAME : string
>'share' : "share"
>iconProp : string
>'test' : "test"
// Nested typing works here and we also get an expected error:
const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
>propB2 : number | IProps
>{ nestedProp: { asdfasdf: 'test' }, iconProp: 'test' } : { nestedProp: { asdfasdf: string; }; iconProp: string; }
>nestedProp : { asdfasdf: string; }
>{ asdfasdf: 'test' } : { asdfasdf: string; }
>asdfasdf : string
>'test' : "test"
>iconProp : string
>'test' : "test"
// Want an error generated here but there isn't one.
const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
>propA1 : number | INestedProps
>{ nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } } : { nestedProps: { INVALID_PROP_NAME: string; iconProp: string; }; }
>nestedProps : { INVALID_PROP_NAME: string; iconProp: string; }
>{ INVALID_PROP_NAME: 'share', iconProp: 'test' } : { INVALID_PROP_NAME: string; iconProp: string; }
>INVALID_PROP_NAME : string
>'share' : "share"
>iconProp : string
>'test' : "test"
@@ -0,0 +1,77 @@
//// [/src/core/anotherModule.d.ts]
export declare const World = "hello";
//// [/src/core/index.d.ts]
export declare const someString: string;
export declare function leftPad(s: string, n: number): string;
export declare function multiply(a: number, b: number): number;
//// [/src/core/tsconfig.json]
{
"compilerOptions": {
"incremental": true, "declaration": true,
"skipDefaultLibCheck": true
}
}
//// [/src/core/tsconfig.tsbuildinfo]
{
"program": {
"fileInfos": {
"/lib/lib.d.ts": {
"version": "/lib/lib.d.ts",
"signature": "/lib/lib.d.ts"
},
"/lib/lib.es5.d.ts": {
"version": "/lib/lib.es5.d.ts",
"signature": "/lib/lib.es5.d.ts"
},
"/lib/lib.dom.d.ts": {
"version": "/lib/lib.dom.d.ts",
"signature": "/lib/lib.dom.d.ts"
},
"/lib/lib.webworker.importscripts.d.ts": {
"version": "/lib/lib.webworker.importscripts.d.ts",
"signature": "/lib/lib.webworker.importscripts.d.ts"
},
"/lib/lib.scripthost.d.ts": {
"version": "/lib/lib.scripthost.d.ts",
"signature": "/lib/lib.scripthost.d.ts"
},
"/src/core/anothermodule.ts": {
"version": "-2676574883",
"signature": "-8396256275"
},
"/src/core/index.ts": {
"version": "-18749805970",
"signature": "1874987148"
},
"/src/core/some_decl.d.ts": {
"version": "-9253692965",
"signature": "-9253692965"
}
},
"options": {
"incremental": true,
"declaration": true,
"skipDefaultLibCheck": true,
"configFilePath": "/src/core/tsconfig.json"
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"/lib/lib.d.ts",
"/lib/lib.dom.d.ts",
"/lib/lib.es5.d.ts",
"/lib/lib.scripthost.d.ts",
"/lib/lib.webworker.importscripts.d.ts",
"/src/core/anothermodule.ts",
"/src/core/index.ts",
"/src/core/some_decl.d.ts"
]
},
"version": "FakeTSVersion"
}
@@ -0,0 +1,82 @@
//// [/src/core/anotherModule.js]
"use strict";
exports.__esModule = true;
exports.World = "hello";
//// [/src/core/index.js]
"use strict";
exports.__esModule = true;
exports.someString = "HELLO WORLD";
function leftPad(s, n) { return s + n; }
exports.leftPad = leftPad;
function multiply(a, b) { return a * b; }
exports.multiply = multiply;
//// [/src/core/tsconfig.json]
{
"compilerOptions": {
"incremental": true,
"skipDefaultLibCheck": true
}
}
//// [/src/core/tsconfig.tsbuildinfo]
{
"program": {
"fileInfos": {
"/lib/lib.d.ts": {
"version": "/lib/lib.d.ts",
"signature": "/lib/lib.d.ts"
},
"/lib/lib.es5.d.ts": {
"version": "/lib/lib.es5.d.ts",
"signature": "/lib/lib.es5.d.ts"
},
"/lib/lib.dom.d.ts": {
"version": "/lib/lib.dom.d.ts",
"signature": "/lib/lib.dom.d.ts"
},
"/lib/lib.webworker.importscripts.d.ts": {
"version": "/lib/lib.webworker.importscripts.d.ts",
"signature": "/lib/lib.webworker.importscripts.d.ts"
},
"/lib/lib.scripthost.d.ts": {
"version": "/lib/lib.scripthost.d.ts",
"signature": "/lib/lib.scripthost.d.ts"
},
"/src/core/anothermodule.ts": {
"version": "-2676574883",
"signature": "-8396256275"
},
"/src/core/index.ts": {
"version": "-18749805970",
"signature": "1874987148"
},
"/src/core/some_decl.d.ts": {
"version": "-9253692965",
"signature": "-9253692965"
}
},
"options": {
"incremental": true,
"skipDefaultLibCheck": true,
"configFilePath": "/src/core/tsconfig.json"
},
"referencedMap": {},
"exportedModulesMap": {},
"semanticDiagnosticsPerFile": [
"/lib/lib.d.ts",
"/lib/lib.dom.d.ts",
"/lib/lib.es5.d.ts",
"/lib/lib.scripthost.d.ts",
"/lib/lib.webworker.importscripts.d.ts",
"/src/core/anothermodule.ts",
"/src/core/index.ts",
"/src/core/some_decl.d.ts"
]
},
"version": "FakeTSVersion"
}
@@ -0,0 +1,17 @@
//// [unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts]
interface IStringDictionary<V> {
[name: string]: V;
}
interface INumberDictionary<V> {
[idx: number]: V;
}
declare function forEach<T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any);
let count = 0;
forEach({ toString: 123 }, () => count++);
//// [unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.js]
var count = 0;
forEach({ toString: 123 }, function () { return count++; });
@@ -0,0 +1,41 @@
=== tests/cases/compiler/unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts ===
interface IStringDictionary<V> {
>IStringDictionary : Symbol(IStringDictionary, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 0, 0))
>V : Symbol(V, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 0, 28))
[name: string]: V;
>name : Symbol(name, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 1, 2))
>V : Symbol(V, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 0, 28))
}
interface INumberDictionary<V> {
>INumberDictionary : Symbol(INumberDictionary, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 2, 1))
>V : Symbol(V, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 3, 28))
[idx: number]: V;
>idx : Symbol(idx, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 4, 2))
>V : Symbol(V, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 3, 28))
}
declare function forEach<T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any);
>forEach : Symbol(forEach, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 5, 1))
>T : Symbol(T, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 25))
>from : Symbol(from, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 28))
>IStringDictionary : Symbol(IStringDictionary, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 0, 0))
>T : Symbol(T, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 25))
>INumberDictionary : Symbol(INumberDictionary, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 2, 1))
>T : Symbol(T, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 25))
>callback : Symbol(callback, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 78))
>entry : Symbol(entry, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 90))
>key : Symbol(key, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 98))
>value : Symbol(value, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 108))
>T : Symbol(T, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 25))
>remove : Symbol(remove, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 7, 121))
let count = 0;
>count : Symbol(count, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 9, 3))
forEach({ toString: 123 }, () => count++);
>forEach : Symbol(forEach, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 5, 1))
>toString : Symbol(toString, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 10, 9))
>count : Symbol(count, Decl(unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts, 9, 3))
@@ -0,0 +1,33 @@
=== tests/cases/compiler/unionExcessPropertyCheckNoApparentPropTypeMismatchErrors.ts ===
interface IStringDictionary<V> {
[name: string]: V;
>name : string
}
interface INumberDictionary<V> {
[idx: number]: V;
>idx : number
}
declare function forEach<T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any);
>forEach : <T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any) => any
>from : IStringDictionary<T> | INumberDictionary<T>
>callback : (entry: { key: any; value: T; }, remove: () => void) => any
>entry : { key: any; value: T; }
>key : any
>value : T
>remove : () => void
let count = 0;
>count : number
>0 : 0
forEach({ toString: 123 }, () => count++);
>forEach({ toString: 123 }, () => count++) : any
>forEach : <T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any) => any
>{ toString: 123 } : { toString: number; }
>toString : number
>123 : 123
>() => count++ : () => number
>count++ : number
>count : number
@@ -0,0 +1,31 @@
//// [unionExcessPropsWithPartialMember.ts]
interface A {
unused?: string;
x: string;
}
interface B {
x: string;
y: string;
}
declare var ab: A | B;
declare var a: A;
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
//// [unionExcessPropsWithPartialMember.js]
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
ab = __assign({}, a, { y: null }); // Should be allowed, since `y` is missing on `A`
@@ -0,0 +1,35 @@
=== tests/cases/compiler/unionExcessPropsWithPartialMember.ts ===
interface A {
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
unused?: string;
>unused : Symbol(A.unused, Decl(unionExcessPropsWithPartialMember.ts, 0, 13))
x: string;
>x : Symbol(A.x, Decl(unionExcessPropsWithPartialMember.ts, 1, 20))
}
interface B {
>B : Symbol(B, Decl(unionExcessPropsWithPartialMember.ts, 3, 1))
x: string;
>x : Symbol(B.x, Decl(unionExcessPropsWithPartialMember.ts, 5, 13))
y: string;
>y : Symbol(B.y, Decl(unionExcessPropsWithPartialMember.ts, 6, 14))
}
declare var ab: A | B;
>ab : Symbol(ab, Decl(unionExcessPropsWithPartialMember.ts, 10, 11))
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
>B : Symbol(B, Decl(unionExcessPropsWithPartialMember.ts, 3, 1))
declare var a: A;
>a : Symbol(a, Decl(unionExcessPropsWithPartialMember.ts, 11, 11))
>A : Symbol(A, Decl(unionExcessPropsWithPartialMember.ts, 0, 0))
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
>ab : Symbol(ab, Decl(unionExcessPropsWithPartialMember.ts, 10, 11))
>a : Symbol(a, Decl(unionExcessPropsWithPartialMember.ts, 11, 11))
>y : Symbol(y, Decl(unionExcessPropsWithPartialMember.ts, 13, 11))
@@ -0,0 +1,34 @@
=== tests/cases/compiler/unionExcessPropsWithPartialMember.ts ===
interface A {
unused?: string;
>unused : string | undefined
x: string;
>x : string
}
interface B {
x: string;
>x : string
y: string;
>y : string
}
declare var ab: A | B;
>ab : A | B
declare var a: A;
>a : A
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`
>ab = {...a, y: (null as any as string | undefined)} : { y: string | undefined; unused?: string | undefined; x: string; }
>ab : A | B
>{...a, y: (null as any as string | undefined)} : { y: string | undefined; unused?: string | undefined; x: string; }
>a : A
>y : string | undefined
>(null as any as string | undefined) : string | undefined
>null as any as string | undefined : string | undefined
>null as any : any
>null : null
@@ -0,0 +1,27 @@
interface StatelessComponent<P = {}> {
(props: P & { children?: number }, context?: any): null;
}
const TestComponent: StatelessComponent<TestProps> = (props) => {
return null;
}
interface ITestProps {
ariaLabel?: string;
}
interface NestedProp<TProps> {
props: TProps;
}
interface TestProps {
icon: NestedProp<ITestProps>;
}
TestComponent({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
const TestComponent2: StatelessComponent<TestProps | {props2: {x: number}}> = (props) => {
return null;
}
TestComponent2({icon: { props: { INVALID_PROP_NAME: 'share', ariaLabel: 'test label' } }});
@@ -0,0 +1,70 @@
// https://github.com/Microsoft/TypeScript/issues/13813
interface A {
x: string
}
interface B {
a: A;
}
interface C {
c: number;
}
type D = B & C;
let a: B = { a: { x: 'hello' } }; // ok
let b: B = { a: { x: 2 } }; // error - types of property x are incompatible
let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
// https://github.com/Microsoft/TypeScript/issues/18075
export type MyType = { id: number; } & { name: string; } & { photo: { id: number; } & { url: string; } }
export let obj: MyType;
export const photo: typeof obj.photo = {
id: 1,
url: '',
xyz: 1 // Great! This causes an error!
};
export const myInstance: MyType = {
id: 1,
name: '',
photo: {
id: 1,
url: '',
xyz: 2 // This should also be an error
}
};
// https://github.com/Microsoft/TypeScript/issues/28616
export type View<T> = { [K in keyof T]: T[K] extends object ? boolean | View<T[K]> : boolean };
interface TypeC {
foo: string;
bar: string;
}
interface TypeB {
foo: string,
bar: TypeC
}
interface TypeA {
foo: string,
bar: TypeB,
}
let test: View<TypeA>;
test = { foo: true, bar: true, boo: true }
test = { foo: true, bar: { foo: true, bar: true, boo: true } }
@@ -1,3 +1,11 @@
declare const fn: <K extends string, V>(object: { [Key in K]: V }) => object;
declare const a: { [index: string]: number };
fn(a);
// Repro from #30218
declare function enumValues<K extends string, V extends string>(e: Record<K, V>): V[];
enum E { A = 'foo', B = 'bar' }
let x: E[] = enumValues(E);
@@ -0,0 +1,19 @@
interface IProps {
iconProp?: string;
nestedProp?: {
testBool?: boolean;
}
}
interface INestedProps {
nestedProps?: IProps;
}
// These are the types of errors we want:
const propB1: IProps | number = { INVALID_PROP_NAME: 'share', iconProp: 'test' };
// Nested typing works here and we also get an expected error:
const propB2: IProps | number = { nestedProp: { asdfasdf: 'test' }, iconProp: 'test' };
// Want an error generated here but there isn't one.
const propA1: INestedProps | number = { nestedProps: { INVALID_PROP_NAME: 'share', iconProp: 'test' } };
@@ -0,0 +1,11 @@
interface IStringDictionary<V> {
[name: string]: V;
}
interface INumberDictionary<V> {
[idx: number]: V;
}
declare function forEach<T>(from: IStringDictionary<T> | INumberDictionary<T>, callback: (entry: { key: any; value: T; }, remove: () => void) => any);
let count = 0;
forEach({ toString: 123 }, () => count++);
@@ -0,0 +1,15 @@
// @strict: true
interface A {
unused?: string;
x: string;
}
interface B {
x: string;
y: string;
}
declare var ab: A | B;
declare var a: A;
ab = {...a, y: (null as any as string | undefined)}; // Should be allowed, since `y` is missing on `A`