mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Make the unconstrained type parameter and {} assignability rule not apply under strictNullChecks (#48366)
* Make the unconstrained type parameter and {} assignability rule not apply under strictNullChecks
* Fix lint, PR feedback
This commit is contained in:
@@ -18702,6 +18702,9 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
reportRelationError(headMessage, source, target);
|
||||
if (strictNullChecks && source.flags & TypeFlags.TypeVariable && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable) && isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) {
|
||||
associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_probably_needs_an_extends_object_constraint));
|
||||
}
|
||||
}
|
||||
|
||||
function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void {
|
||||
@@ -19492,7 +19495,7 @@ namespace ts {
|
||||
// IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch
|
||||
if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) {
|
||||
const constraint = getConstraintOfType(source as TypeVariable);
|
||||
if (!constraint || (sourceFlags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) {
|
||||
if (!strictNullChecks && (!constraint || (sourceFlags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any))) {
|
||||
// A type variable with no constraint is not related to the non-primitive object type.
|
||||
if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive), RecursionFlags.Both)) {
|
||||
resetErrorInfo(saveErrorInfo);
|
||||
@@ -19500,12 +19503,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
// hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed
|
||||
else if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) {
|
||||
else if (constraint && (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState))) {
|
||||
resetErrorInfo(saveErrorInfo);
|
||||
return result;
|
||||
}
|
||||
// slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example
|
||||
else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) {
|
||||
else if (constraint && (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState))) {
|
||||
resetErrorInfo(saveErrorInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace ts {
|
||||
array.length = outIndex;
|
||||
}
|
||||
|
||||
export function clear(array: {}[]): void {
|
||||
export function clear(array: unknown[]): void {
|
||||
array.length = 0;
|
||||
}
|
||||
|
||||
@@ -1644,7 +1644,7 @@ namespace ts {
|
||||
/**
|
||||
* Tests whether a value is an array.
|
||||
*/
|
||||
export function isArray(value: any): value is readonly {}[] {
|
||||
export function isArray(value: any): value is readonly unknown[] {
|
||||
return Array.isArray ? Array.isArray(value) : value instanceof Array;
|
||||
}
|
||||
|
||||
@@ -1677,7 +1677,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Does nothing. */
|
||||
export function noop(_?: {} | null | undefined): void { }
|
||||
export function noop(_?: unknown): void { }
|
||||
|
||||
/** Do nothing and return false */
|
||||
export function returnFalse(): false {
|
||||
|
||||
@@ -1506,6 +1506,10 @@
|
||||
"category": "Error",
|
||||
"code": 2207
|
||||
},
|
||||
"This type parameter probably needs an `extends object` constraint.": {
|
||||
"category": "Error",
|
||||
"code": 2208
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -20,8 +20,8 @@ globalThis.assert = _chai.assert;
|
||||
}
|
||||
assertDeepImpl(a, b, msg);
|
||||
|
||||
function arrayExtraKeysObject(a: readonly ({} | null | undefined)[]): object {
|
||||
const obj: { [key: string]: {} | null | undefined } = {};
|
||||
function arrayExtraKeysObject(a: readonly unknown[]): object {
|
||||
const obj: { [key: string]: unknown } = {};
|
||||
for (const key in a) {
|
||||
if (Number.isNaN(Number(key))) {
|
||||
obj[key] = a[key];
|
||||
|
||||
@@ -554,7 +554,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): {} {
|
||||
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => unknown, logPerformance: boolean): unknown {
|
||||
let start: number | undefined;
|
||||
if (logPerformance) {
|
||||
logger.log(actionDescription);
|
||||
|
||||
@@ -23,7 +23,7 @@ function boxify<T>(obj: T): Boxified<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
function unboxify<T>(obj: Boxified<T>): T {
|
||||
function unboxify<T extends object>(obj: Boxified<T>): T {
|
||||
let result = {} as T;
|
||||
for (let k in obj) {
|
||||
result[k] = unbox(obj[k]);
|
||||
@@ -307,7 +307,7 @@ declare type Boxified<T> = {
|
||||
declare function box<T>(x: T): Box<T>;
|
||||
declare function unbox<T>(x: Box<T>): T;
|
||||
declare function boxify<T>(obj: T): Boxified<T>;
|
||||
declare function unboxify<T>(obj: Boxified<T>): T;
|
||||
declare function unboxify<T extends object>(obj: Boxified<T>): T;
|
||||
declare function assignBoxified<T>(obj: Boxified<T>, values: T): void;
|
||||
declare function f1(): void;
|
||||
declare function f2(): void;
|
||||
|
||||
@@ -75,10 +75,10 @@ function boxify<T>(obj: T): Boxified<T> {
|
||||
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 17, 7))
|
||||
}
|
||||
|
||||
function unboxify<T>(obj: Boxified<T>): T {
|
||||
function unboxify<T extends object>(obj: Boxified<T>): T {
|
||||
>unboxify : Symbol(unboxify, Decl(isomorphicMappedTypeInference.ts, 22, 1))
|
||||
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 24, 18))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 21))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 36))
|
||||
>Boxified : Symbol(Boxified, Decl(isomorphicMappedTypeInference.ts, 2, 1))
|
||||
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 24, 18))
|
||||
>T : Symbol(T, Decl(isomorphicMappedTypeInference.ts, 24, 18))
|
||||
@@ -89,13 +89,13 @@ function unboxify<T>(obj: Boxified<T>): T {
|
||||
|
||||
for (let k in obj) {
|
||||
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 26, 12))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 21))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 36))
|
||||
|
||||
result[k] = unbox(obj[k]);
|
||||
>result : Symbol(result, Decl(isomorphicMappedTypeInference.ts, 25, 7))
|
||||
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 26, 12))
|
||||
>unbox : Symbol(unbox, Decl(isomorphicMappedTypeInference.ts, 10, 1))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 21))
|
||||
>obj : Symbol(obj, Decl(isomorphicMappedTypeInference.ts, 24, 36))
|
||||
>k : Symbol(k, Decl(isomorphicMappedTypeInference.ts, 26, 12))
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -60,8 +60,8 @@ function boxify<T>(obj: T): Boxified<T> {
|
||||
>result : Boxified<T>
|
||||
}
|
||||
|
||||
function unboxify<T>(obj: Boxified<T>): T {
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
function unboxify<T extends object>(obj: Boxified<T>): T {
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>obj : Boxified<T>
|
||||
|
||||
let result = {} as T;
|
||||
@@ -174,7 +174,7 @@ function f2() {
|
||||
let v = unboxify(b);
|
||||
>v : { a: number; b: string; c: boolean; }
|
||||
>unboxify(b) : { a: number; b: string; c: boolean; }
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
|
||||
let x: number = v.a;
|
||||
@@ -251,14 +251,14 @@ function f4() {
|
||||
>boxify(unboxify(b)) : Boxified<{ a: number; b: string; c: boolean; }>
|
||||
>boxify : <T>(obj: T) => Boxified<T>
|
||||
>unboxify(b) : { a: number; b: string; c: boolean; }
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
|
||||
b = unboxify(boxify(b));
|
||||
>b = unboxify(boxify(b)) : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
>unboxify(boxify(b)) : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>boxify(b) : Boxified<{ a: Box<number>; b: Box<string>; c: Box<boolean>; }>
|
||||
>boxify : <T>(obj: T) => Boxified<T>
|
||||
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
|
||||
@@ -304,7 +304,7 @@ function f5(s: string) {
|
||||
let v = unboxify(b);
|
||||
>v : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
|
||||
>unboxify(b) : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>b : { a: Box<number> | Box<string> | Box<boolean>; b: Box<number> | Box<string> | Box<boolean>; c: Box<number> | Box<string> | Box<boolean>; }
|
||||
|
||||
let x: string | number | boolean = v.a;
|
||||
@@ -355,7 +355,7 @@ function f6(s: string) {
|
||||
let v = unboxify(b);
|
||||
>v : { [x: string]: any; }
|
||||
>unboxify(b) : { [x: string]: any; }
|
||||
>unboxify : <T>(obj: Boxified<T>) => T
|
||||
>unboxify : <T extends object>(obj: Boxified<T>) => T
|
||||
>b : { [x: string]: Box<number> | Box<string> | Box<boolean>; }
|
||||
|
||||
let x: string | number | boolean = v[s];
|
||||
|
||||
@@ -0,0 +1,709 @@
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(316,5): error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(317,5): error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
|
||||
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
|
||||
Type 'T[string]' is not assignable to type '{}'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(318,5): error TS2322: Type 'T[K]' is not assignable to type '{}'.
|
||||
Type 'T[keyof T]' is not assignable to type '{}'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(323,5): error TS2322: Type 'T' is not assignable to type '{} | null | undefined'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(324,5): error TS2322: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(325,5): error TS2322: Type 'T[K]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(611,33): error TS2345: Argument of type 'T[K]' is not assignable to parameter of type '{} | null | undefined'.
|
||||
Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(619,13): error TS2322: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts (8 errors) ====
|
||||
class Shape {
|
||||
name: string;
|
||||
width: number;
|
||||
height: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
class TaggedShape extends Shape {
|
||||
tag: string;
|
||||
}
|
||||
|
||||
class Item {
|
||||
name: string;
|
||||
price: number;
|
||||
}
|
||||
|
||||
class Options {
|
||||
visible: "yes" | "no";
|
||||
}
|
||||
|
||||
type Dictionary<T> = { [x: string]: T };
|
||||
type NumericallyIndexed<T> = { [x: number]: T };
|
||||
|
||||
const enum E { A, B, C }
|
||||
|
||||
type K00 = keyof any; // string
|
||||
type K01 = keyof string; // "toString" | "charAt" | ...
|
||||
type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ...
|
||||
type K03 = keyof boolean; // "valueOf"
|
||||
type K04 = keyof void; // never
|
||||
type K05 = keyof undefined; // never
|
||||
type K06 = keyof null; // never
|
||||
type K07 = keyof never; // string | number | symbol
|
||||
type K08 = keyof unknown; // never
|
||||
|
||||
type K10 = keyof Shape; // "name" | "width" | "height" | "visible"
|
||||
type K11 = keyof Shape[]; // "length" | "toString" | ...
|
||||
type K12 = keyof Dictionary<Shape>; // string
|
||||
type K13 = keyof {}; // never
|
||||
type K14 = keyof Object; // "constructor" | "toString" | ...
|
||||
type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ...
|
||||
type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ...
|
||||
type K17 = keyof (Shape | Item); // "name"
|
||||
type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price"
|
||||
type K19 = keyof NumericallyIndexed<Shape> // never
|
||||
|
||||
type KeyOf<T> = keyof T;
|
||||
|
||||
type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible"
|
||||
type K21 = KeyOf<Dictionary<Shape>>; // string
|
||||
|
||||
type NAME = "name";
|
||||
type WIDTH_OR_HEIGHT = "width" | "height";
|
||||
|
||||
type Q10 = Shape["name"]; // string
|
||||
type Q11 = Shape["width" | "height"]; // number
|
||||
type Q12 = Shape["name" | "visible"]; // string | boolean
|
||||
|
||||
type Q20 = Shape[NAME]; // string
|
||||
type Q21 = Shape[WIDTH_OR_HEIGHT]; // number
|
||||
|
||||
type Q30 = [string, number][0]; // string
|
||||
type Q31 = [string, number][1]; // number
|
||||
type Q32 = [string, number][number]; // string | number
|
||||
type Q33 = [string, number][E.A]; // string
|
||||
type Q34 = [string, number][E.B]; // number
|
||||
type Q35 = [string, number]["0"]; // string
|
||||
type Q36 = [string, number]["1"]; // string
|
||||
|
||||
type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no"
|
||||
type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no"
|
||||
|
||||
type Q50 = Dictionary<Shape>["howdy"]; // Shape
|
||||
type Q51 = Dictionary<Shape>[123]; // Shape
|
||||
type Q52 = Dictionary<Shape>[E.B]; // Shape
|
||||
|
||||
declare let cond: boolean;
|
||||
|
||||
function getProperty<T, K extends keyof T>(obj: T, key: K) {
|
||||
return obj[key];
|
||||
}
|
||||
|
||||
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
|
||||
obj[key] = value;
|
||||
}
|
||||
|
||||
function f10(shape: Shape) {
|
||||
let name = getProperty(shape, "name"); // string
|
||||
let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number
|
||||
let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean
|
||||
setProperty(shape, "name", "rectangle");
|
||||
setProperty(shape, cond ? "width" : "height", 10);
|
||||
setProperty(shape, cond ? "name" : "visible", true); // Technically not safe
|
||||
}
|
||||
|
||||
function f11(a: Shape[]) {
|
||||
let len = getProperty(a, "length"); // number
|
||||
setProperty(a, "length", len);
|
||||
}
|
||||
|
||||
function f12(t: [Shape, boolean]) {
|
||||
let len = getProperty(t, "length");
|
||||
let s2 = getProperty(t, "0"); // Shape
|
||||
let b2 = getProperty(t, "1"); // boolean
|
||||
}
|
||||
|
||||
function f13(foo: any, bar: any) {
|
||||
let x = getProperty(foo, "x"); // any
|
||||
let y = getProperty(foo, "100"); // any
|
||||
let z = getProperty(foo, bar); // any
|
||||
}
|
||||
|
||||
class Component<PropType> {
|
||||
props: PropType;
|
||||
getProperty<K extends keyof PropType>(key: K) {
|
||||
return this.props[key];
|
||||
}
|
||||
setProperty<K extends keyof PropType>(key: K, value: PropType[K]) {
|
||||
this.props[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function f20(component: Component<Shape>) {
|
||||
let name = component.getProperty("name"); // string
|
||||
let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number
|
||||
let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean
|
||||
component.setProperty("name", "rectangle");
|
||||
component.setProperty(cond ? "width" : "height", 10)
|
||||
component.setProperty(cond ? "name" : "visible", true); // Technically not safe
|
||||
}
|
||||
|
||||
function pluck<T, K extends keyof T>(array: T[], key: K) {
|
||||
return array.map(x => x[key]);
|
||||
}
|
||||
|
||||
function f30(shapes: Shape[]) {
|
||||
let names = pluck(shapes, "name"); // string[]
|
||||
let widths = pluck(shapes, "width"); // number[]
|
||||
let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[]
|
||||
}
|
||||
|
||||
function f31<K extends keyof Shape>(key: K) {
|
||||
const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
|
||||
return shape[key]; // Shape[K]
|
||||
}
|
||||
|
||||
function f32<K extends "width" | "height">(key: K) {
|
||||
const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
|
||||
return shape[key]; // Shape[K]
|
||||
}
|
||||
|
||||
function f33<S extends Shape, K extends keyof S>(shape: S, key: K) {
|
||||
let name = getProperty(shape, "name");
|
||||
let prop = getProperty(shape, key);
|
||||
return prop;
|
||||
}
|
||||
|
||||
function f34(ts: TaggedShape) {
|
||||
let tag1 = f33(ts, "tag");
|
||||
let tag2 = getProperty(ts, "tag");
|
||||
}
|
||||
|
||||
class C {
|
||||
public x: string;
|
||||
protected y: string;
|
||||
private z: string;
|
||||
}
|
||||
|
||||
// Indexed access expressions have always permitted access to private and protected members.
|
||||
// For consistency we also permit such access in indexed access types.
|
||||
function f40(c: C) {
|
||||
type X = C["x"];
|
||||
type Y = C["y"];
|
||||
type Z = C["z"];
|
||||
let x: X = c["x"];
|
||||
let y: Y = c["y"];
|
||||
let z: Z = c["z"];
|
||||
}
|
||||
|
||||
function f50<T>(k: keyof T, s: string) {
|
||||
const x1 = s as keyof T;
|
||||
const x2 = k as string;
|
||||
}
|
||||
|
||||
function f51<T, K extends keyof T>(k: K, s: string) {
|
||||
const x1 = s as keyof T;
|
||||
const x2 = k as string;
|
||||
}
|
||||
|
||||
function f52<T>(obj: { [x: string]: boolean }, k: Exclude<keyof T, symbol>, s: string, n: number) {
|
||||
const x1 = obj[s];
|
||||
const x2 = obj[n];
|
||||
const x3 = obj[k];
|
||||
}
|
||||
|
||||
function f53<T, K extends Exclude<keyof T, symbol>>(obj: { [x: string]: boolean }, k: K, s: string, n: number) {
|
||||
const x1 = obj[s];
|
||||
const x2 = obj[n];
|
||||
const x3 = obj[k];
|
||||
}
|
||||
|
||||
function f54<T>(obj: T, key: keyof T) {
|
||||
for (let s in obj[key]) {
|
||||
}
|
||||
const b = "foo" in obj[key];
|
||||
}
|
||||
|
||||
function f55<T, K extends keyof T>(obj: T, key: K) {
|
||||
for (let s in obj[key]) {
|
||||
}
|
||||
const b = "foo" in obj[key];
|
||||
}
|
||||
|
||||
function f60<T>(source: T, target: T) {
|
||||
for (let k in source) {
|
||||
target[k] = source[k];
|
||||
}
|
||||
}
|
||||
|
||||
function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
|
||||
func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
|
||||
func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
|
||||
func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
|
||||
}
|
||||
|
||||
function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
|
||||
let x = func({ a: 1, b: "hello" }, { c: true });
|
||||
x.a; // number | undefined
|
||||
x.b; // string | undefined
|
||||
x.c; // boolean | undefined
|
||||
}
|
||||
|
||||
function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
|
||||
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
|
||||
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
|
||||
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
|
||||
}
|
||||
|
||||
function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
|
||||
let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
|
||||
let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
|
||||
let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
|
||||
}
|
||||
|
||||
function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
|
||||
let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
|
||||
let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
|
||||
}
|
||||
|
||||
function f80<T extends { a: { x: any } }>(obj: T) {
|
||||
let a1 = obj.a; // { x: any }
|
||||
let a2 = obj['a']; // { x: any }
|
||||
let a3 = obj['a'] as T['a']; // T["a"]
|
||||
let x1 = obj.a.x; // any
|
||||
let x2 = obj['a']['x']; // any
|
||||
let x3 = obj['a']['x'] as T['a']['x']; // T["a"]["x"]
|
||||
}
|
||||
|
||||
function f81<T extends { a: { x: any } }>(obj: T) {
|
||||
return obj['a']['x'] as T['a']['x'];
|
||||
}
|
||||
|
||||
function f82() {
|
||||
let x1 = f81({ a: { x: "hello" } }); // string
|
||||
let x2 = f81({ a: { x: 42 } }); // number
|
||||
}
|
||||
|
||||
function f83<T extends { [x: string]: { x: any } }, K extends keyof T>(obj: T, key: K) {
|
||||
return obj[key]['x'] as T[K]['x'];
|
||||
}
|
||||
|
||||
function f84() {
|
||||
let x1 = f83({ foo: { x: "hello" } }, "foo"); // string
|
||||
let x2 = f83({ bar: { x: 42 } }, "bar"); // number
|
||||
}
|
||||
|
||||
class C1 {
|
||||
x: number;
|
||||
get<K extends keyof this>(key: K) {
|
||||
return this[key];
|
||||
}
|
||||
set<K extends keyof this>(key: K, value: this[K]) {
|
||||
this[key] = value;
|
||||
}
|
||||
foo() {
|
||||
let x1 = this.x; // number
|
||||
let x2 = this["x"]; // number
|
||||
let x3 = this.get("x"); // this["x"]
|
||||
let x4 = getProperty(this, "x"); // this["x"]
|
||||
this.x = 42;
|
||||
this["x"] = 42;
|
||||
this.set("x", 42);
|
||||
setProperty(this, "x", 42);
|
||||
}
|
||||
}
|
||||
|
||||
type S2 = {
|
||||
a: string;
|
||||
b: string;
|
||||
};
|
||||
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) {
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
x1.length;
|
||||
x2.length;
|
||||
x3.length;
|
||||
}
|
||||
|
||||
function f91<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
|
||||
let a: {};
|
||||
a = x;
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
!!! related TS2208 tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts:314:14: This type parameter probably needs an `extends object` constraint.
|
||||
a = y;
|
||||
~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
|
||||
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{}'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type '{}'.
|
||||
a = z;
|
||||
~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type '{}'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{}'.
|
||||
}
|
||||
|
||||
function f92<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
|
||||
let a: {} | null | undefined;
|
||||
a = x;
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type '{} | null | undefined'.
|
||||
!!! related TS2208 tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts:321:14: This type parameter probably needs an `extends object` constraint.
|
||||
a = y;
|
||||
~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
a = z;
|
||||
~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
}
|
||||
|
||||
// Repros from #12011
|
||||
|
||||
class Base {
|
||||
get<K extends keyof this>(prop: K) {
|
||||
return this[prop];
|
||||
}
|
||||
set<K extends keyof this>(prop: K, value: this[K]) {
|
||||
this[prop] = value;
|
||||
}
|
||||
}
|
||||
|
||||
class Person extends Base {
|
||||
parts: number;
|
||||
constructor(parts: number) {
|
||||
super();
|
||||
this.set("parts", parts);
|
||||
}
|
||||
getParts() {
|
||||
return this.get("parts")
|
||||
}
|
||||
}
|
||||
|
||||
class OtherPerson {
|
||||
parts: number;
|
||||
constructor(parts: number) {
|
||||
setProperty(this, "parts", parts);
|
||||
}
|
||||
getParts() {
|
||||
return getProperty(this, "parts")
|
||||
}
|
||||
}
|
||||
|
||||
// Modified repro from #12544
|
||||
|
||||
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
|
||||
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
|
||||
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
|
||||
function path(obj: any, ...keys: (string | number)[]): any;
|
||||
function path(obj: any, ...keys: (string | number)[]): any {
|
||||
let result = obj;
|
||||
for (let k of keys) {
|
||||
result = result[k];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
type Thing = {
|
||||
a: { x: number, y: string },
|
||||
b: boolean
|
||||
};
|
||||
|
||||
|
||||
function f1(thing: Thing) {
|
||||
let x1 = path(thing, 'a'); // { x: number, y: string }
|
||||
let x2 = path(thing, 'a', 'y'); // string
|
||||
let x3 = path(thing, 'b'); // boolean
|
||||
let x4 = path(thing, ...['a', 'x']); // any
|
||||
}
|
||||
|
||||
// Repro from comment in #12114
|
||||
|
||||
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
|
||||
(value: T[K1][K2]) => object[key1][key2] = value;
|
||||
|
||||
// Modified repro from #12573
|
||||
|
||||
declare function one<T>(handler: (t: T) => void): T
|
||||
var empty = one(() => {}) // inferred as {}, expected
|
||||
|
||||
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
|
||||
declare function on<T>(handlerHash: Handlers<T>): T
|
||||
var hashOfEmpty1 = on({ test: () => {} }); // {}
|
||||
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
|
||||
|
||||
// Repro from #12624
|
||||
|
||||
interface Options1<Data, Computed> {
|
||||
data?: Data
|
||||
computed?: Computed;
|
||||
}
|
||||
|
||||
declare class Component1<Data, Computed> {
|
||||
constructor(options: Options1<Data, Computed>);
|
||||
get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
|
||||
}
|
||||
|
||||
let c1 = new Component1({
|
||||
data: {
|
||||
hello: ""
|
||||
}
|
||||
});
|
||||
|
||||
c1.get("hello");
|
||||
|
||||
// Repro from #12625
|
||||
|
||||
interface Options2<Data, Computed> {
|
||||
data?: Data
|
||||
computed?: Computed;
|
||||
}
|
||||
|
||||
declare class Component2<Data, Computed> {
|
||||
constructor(options: Options2<Data, Computed>);
|
||||
get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
|
||||
}
|
||||
|
||||
// Repro from #12641
|
||||
|
||||
interface R {
|
||||
p: number;
|
||||
}
|
||||
|
||||
function f<K extends keyof R>(p: K) {
|
||||
let a: any;
|
||||
a[p].add; // any
|
||||
}
|
||||
|
||||
// Repro from #12651
|
||||
|
||||
type MethodDescriptor = {
|
||||
name: string;
|
||||
args: any[];
|
||||
returnValue: any;
|
||||
}
|
||||
|
||||
declare function dispatchMethod<M extends MethodDescriptor>(name: M['name'], args: M['args']): M['returnValue'];
|
||||
|
||||
type SomeMethodDescriptor = {
|
||||
name: "someMethod";
|
||||
args: [string, number];
|
||||
returnValue: string[];
|
||||
}
|
||||
|
||||
let result = dispatchMethod<SomeMethodDescriptor>("someMethod", ["hello", 35]);
|
||||
|
||||
// Repro from #13073
|
||||
|
||||
type KeyTypes = "a" | "b"
|
||||
let MyThingy: { [key in KeyTypes]: string[] };
|
||||
|
||||
function addToMyThingy<S extends KeyTypes>(key: S) {
|
||||
MyThingy[key].push("a");
|
||||
}
|
||||
|
||||
// Repro from #13102
|
||||
|
||||
type Handler<T> = {
|
||||
onChange: (name: keyof T) => void;
|
||||
};
|
||||
|
||||
function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
|
||||
handler.onChange('preset')
|
||||
}
|
||||
|
||||
// Repro from #13285
|
||||
|
||||
function updateIds<T extends Record<K, string>, K extends string>(
|
||||
obj: T,
|
||||
idFields: K[],
|
||||
idMapping: Partial<Record<T[K], T[K]>>
|
||||
): Record<K, string> {
|
||||
for (const idField of idFields) {
|
||||
const newId: T[K] | undefined = idMapping[obj[idField]];
|
||||
if (newId) {
|
||||
obj[idField] = newId;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Repro from #13285
|
||||
|
||||
function updateIds2<T extends { [x: string]: string }, K extends keyof T>(
|
||||
obj: T,
|
||||
key: K,
|
||||
stringMap: { [oldId: string]: string }
|
||||
) {
|
||||
var x = obj[key];
|
||||
stringMap[x]; // Should be OK.
|
||||
}
|
||||
|
||||
// Repro from #13514
|
||||
|
||||
declare function head<T extends Array<any>>(list: T): T[0];
|
||||
|
||||
// Repro from #13604
|
||||
|
||||
class A<T> {
|
||||
props: T & { foo: string };
|
||||
}
|
||||
|
||||
class B extends A<{ x: number}> {
|
||||
f(p: this["props"]) {
|
||||
p.x;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #13749
|
||||
|
||||
class Form<T> {
|
||||
private childFormFactories: {[K in keyof T]: (v: T[K]) => Form<T[K]>}
|
||||
|
||||
public set<K extends keyof T>(prop: K, value: T[K]) {
|
||||
this.childFormFactories[prop](value)
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #13787
|
||||
|
||||
class SampleClass<P> {
|
||||
public props: Readonly<P>;
|
||||
constructor(props: P) {
|
||||
this.props = Object.freeze(props);
|
||||
}
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
foo: string;
|
||||
}
|
||||
|
||||
declare function merge<T, U>(obj1: T, obj2: U): T & U;
|
||||
|
||||
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
|
||||
constructor(props: T) {
|
||||
const foo: Foo = { foo: "bar" };
|
||||
super(merge(props, foo));
|
||||
}
|
||||
|
||||
public brokenMethod() {
|
||||
this.props.foo.concat;
|
||||
}
|
||||
}
|
||||
new AnotherSampleClass({});
|
||||
|
||||
// Positive repro from #17166
|
||||
function f3<T, K extends Extract<keyof T, string>>(t: T, k: K, tk: T[K]): void {
|
||||
for (let key in t) {
|
||||
key = k // ok, K ==> keyof T
|
||||
t[key] = tk; // ok, T[K] ==> T[keyof T]
|
||||
}
|
||||
}
|
||||
|
||||
// # 21185
|
||||
type Predicates<TaggedRecord> = {
|
||||
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
|
||||
}
|
||||
|
||||
// Repros from #23592
|
||||
|
||||
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
|
||||
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
|
||||
|
||||
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
|
||||
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
|
||||
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
|
||||
|
||||
// Repro from #23618
|
||||
|
||||
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }
|
||||
enum Flag {
|
||||
FLAG_1 = "flag_1",
|
||||
FLAG_2 = "flag_2"
|
||||
}
|
||||
|
||||
type SimpleDBRecord<Flag extends string> = { staticField: number } & DBBoolTable<Flag>
|
||||
function getFlagsFromSimpleRecord<Flag extends string>(record: SimpleDBRecord<Flag>, flags: Flag[]) {
|
||||
return record[flags[0]];
|
||||
}
|
||||
|
||||
type DynamicDBRecord<Flag extends string> = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable<Flag>
|
||||
function getFlagsFromDynamicRecord<Flag extends string>(record: DynamicDBRecord<Flag>, flags: Flag[]) {
|
||||
return record[flags[0]];
|
||||
}
|
||||
|
||||
// Repro from #21368
|
||||
|
||||
interface I {
|
||||
foo: string;
|
||||
}
|
||||
|
||||
declare function take<T>(p: T): void;
|
||||
|
||||
function fn<T extends I, K extends keyof T>(o: T, k: K) {
|
||||
take<{} | null | undefined>(o[k]);
|
||||
~~~~
|
||||
!!! error TS2345: Argument of type 'T[K]' is not assignable to parameter of type '{} | null | undefined'.
|
||||
!!! error TS2345: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2345: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2345: Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
take<any>(o[k]);
|
||||
}
|
||||
|
||||
// Repro from #23133
|
||||
|
||||
class Unbounded<T> {
|
||||
foo(x: T[keyof T]) {
|
||||
let y: {} | undefined | null = x;
|
||||
~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{} | null | undefined'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type '{} | null | undefined'.
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #23940
|
||||
|
||||
interface I7 {
|
||||
x: any;
|
||||
}
|
||||
type Foo7<T extends number> = T;
|
||||
declare function f7<K extends keyof I7>(type: K): Foo7<I7[K]>;
|
||||
|
||||
// Repro from #21770
|
||||
|
||||
type Dict<T extends string> = { [key in T]: number };
|
||||
type DictDict<V extends string, T extends string> = { [key in V]: Dict<T> };
|
||||
|
||||
function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
|
||||
return dd[k1][k2];
|
||||
}
|
||||
|
||||
function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number {
|
||||
const d: Dict<T> = dd[k1];
|
||||
return d[k2];
|
||||
}
|
||||
|
||||
// Repro from #26409
|
||||
|
||||
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts(25,11): error TS2430: Interface 'E1<T>' incorrectly extends interface 'Base'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'T' is not assignable to type '{ [key: string]: any; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts (1 errors) ====
|
||||
function f1<T>(x: Partial<T>, y: Readonly<T>) {
|
||||
let obj: {};
|
||||
obj = x;
|
||||
obj = y;
|
||||
}
|
||||
|
||||
function f2<T>(x: Partial<T>, y: Readonly<T>) {
|
||||
let obj: { [x: string]: any };
|
||||
obj = x;
|
||||
obj = y;
|
||||
}
|
||||
|
||||
function f3<T>(x: Partial<T>) {
|
||||
x = {};
|
||||
}
|
||||
|
||||
// Repro from #12900
|
||||
|
||||
interface Base {
|
||||
foo: { [key: string]: any };
|
||||
bar: any;
|
||||
baz: any;
|
||||
}
|
||||
|
||||
interface E1<T> extends Base {
|
||||
~~
|
||||
!!! error TS2430: Interface 'E1<T>' incorrectly extends interface 'Base'.
|
||||
!!! error TS2430: Types of property 'foo' are incompatible.
|
||||
!!! error TS2430: Type 'T' is not assignable to type '{ [key: string]: any; }'.
|
||||
!!! related TS2208 tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts:25:14: This type parameter probably needs an `extends object` constraint.
|
||||
foo: T;
|
||||
}
|
||||
|
||||
interface Something { name: string, value: string };
|
||||
interface E2 extends Base {
|
||||
foo: Partial<Something>; // or other mapped type
|
||||
}
|
||||
|
||||
interface E3<T> extends Base {
|
||||
foo: Partial<T>; // or other mapped type
|
||||
}
|
||||
|
||||
// Repro from #13747
|
||||
|
||||
class Form<T> {
|
||||
private values: {[P in keyof T]?: T[P]} = {}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,17 @@ tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx(15,14): error TS2769: No o
|
||||
Type '{}' is not assignable to type 'Readonly<P>'.
|
||||
Overload 2 of 2, '(props: P, context?: any): MyComponent', gave the following error.
|
||||
Type '{}' is not assignable to type 'Readonly<P>'.
|
||||
tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx(17,14): error TS2322: Type 'P' is not assignable to type 'IntrinsicAttributes & P'.
|
||||
Type 'P' is not assignable to type 'IntrinsicAttributes'.
|
||||
tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx(18,14): error TS2769: No overload matches this call.
|
||||
Overload 1 of 2, '(props: Readonly<P>): MyComponent', gave the following error.
|
||||
Type 'P' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<{ children?: ReactNode; }> & Readonly<P>'.
|
||||
Type 'P' is not assignable to type 'IntrinsicAttributes'.
|
||||
Overload 2 of 2, '(props: P, context?: any): MyComponent', gave the following error.
|
||||
Type 'P' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<{ children?: ReactNode; }> & Readonly<P>'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx (2 errors) ====
|
||||
==== tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx (4 errors) ====
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
import React from 'react';
|
||||
@@ -34,5 +42,17 @@ tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx(15,14): error TS2769: No o
|
||||
!!! error TS2769: Type '{}' is not assignable to type 'Readonly<P>'.
|
||||
|
||||
let z = <MySFC {...wrappedProps} /> // should work
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'P' is not assignable to type 'IntrinsicAttributes & P'.
|
||||
!!! error TS2322: Type 'P' is not assignable to type 'IntrinsicAttributes'.
|
||||
!!! related TS2208 tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx:5:15: This type parameter probably needs an `extends object` constraint.
|
||||
let q = <MyComponent {...wrappedProps} /> // should work
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2769: No overload matches this call.
|
||||
!!! error TS2769: Overload 1 of 2, '(props: Readonly<P>): MyComponent', gave the following error.
|
||||
!!! error TS2769: Type 'P' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<{ children?: ReactNode; }> & Readonly<P>'.
|
||||
!!! error TS2769: Type 'P' is not assignable to type 'IntrinsicAttributes'.
|
||||
!!! error TS2769: Overload 2 of 2, '(props: P, context?: any): MyComponent', gave the following error.
|
||||
!!! error TS2769: Type 'P' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<{ children?: ReactNode; }> & Readonly<P>'.
|
||||
!!! related TS2208 tests/cases/compiler/tsxNotUsingApparentTypeOfSFC.tsx:5:15: This type parameter probably needs an `extends object` constraint.
|
||||
}
|
||||
@@ -25,13 +25,14 @@ tests/cases/conformance/types/unknown/unknownType1.ts(144,29): error TS2698: Spr
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(150,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(156,14): error TS2700: Rest types may only be created from object types.
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(162,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(170,9): error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(171,9): error TS2322: Type 'U' is not assignable to type '{}'.
|
||||
Type 'unknown' is not assignable to type '{}'.
|
||||
tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
Type 'unknown' is not assignable to type '{}'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/unknown/unknownType1.ts (27 errors) ====
|
||||
==== tests/cases/conformance/types/unknown/unknownType1.ts (28 errors) ====
|
||||
// In an intersection everything absorbs unknown
|
||||
|
||||
type T00 = unknown & null; // null
|
||||
@@ -254,6 +255,9 @@ tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type
|
||||
|
||||
function f30<T, U extends unknown>(t: T, u: U) {
|
||||
let x: {} = t;
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
!!! related TS2208 tests/cases/conformance/types/unknown/unknownType1.ts:169:14: This type parameter probably needs an `extends object` constraint.
|
||||
let y: {} = u;
|
||||
~
|
||||
!!! error TS2322: Type 'U' is not assignable to type '{}'.
|
||||
|
||||
@@ -26,7 +26,7 @@ function boxify<T>(obj: T): Boxified<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
function unboxify<T>(obj: Boxified<T>): T {
|
||||
function unboxify<T extends object>(obj: Boxified<T>): T {
|
||||
let result = {} as T;
|
||||
for (let k in obj) {
|
||||
result[k] = unbox(obj[k]);
|
||||
|
||||
Reference in New Issue
Block a user