TypeScript/tests/baselines/reference/strictOptionalProperties1.types
Anders Hejlsberg 2f0c6070cb
Properly handle missingType in intersections (#46052)
* Properly handle missingType in intersections

* Add regression tests

* Accept new baselines

* Fix tests
2021-09-26 14:13:42 -07:00

815 lines
19 KiB
Plaintext

=== tests/cases/compiler/strictOptionalProperties1.ts ===
function f1(obj: { a?: string, b?: string | undefined }) {
>f1 : (obj: { a?: string; b?: string | undefined; }) => void
>obj : { a?: string; b?: string | undefined; }
>a : string | undefined
>b : string | undefined
let a = obj.a; // string | undefined
>a : string | undefined
>obj.a : string | undefined
>obj : { a?: string; b?: string | undefined; }
>a : string | undefined
let b = obj.b; // string | undefined
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
obj.a = 'hello';
>obj.a = 'hello' : "hello"
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>'hello' : "hello"
obj.b = 'hello';
>obj.b = 'hello' : "hello"
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>'hello' : "hello"
obj.a = undefined; // Error
>obj.a = undefined : undefined
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>undefined : undefined
obj.b = undefined;
>obj.b = undefined : undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>undefined : undefined
}
function f2(obj: { a?: string, b?: string | undefined }) {
>f2 : (obj: { a?: string; b?: string | undefined;}) => void
>obj : { a?: string; b?: string | undefined; }
>a : string | undefined
>b : string | undefined
obj = obj;
>obj = obj : { a?: string; b?: string | undefined; }
>obj : { a?: string; b?: string | undefined; }
>obj : { a?: string; b?: string | undefined; }
obj.a = obj.a; // Error
>obj.a = obj.a : string | undefined
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>obj.a : string | undefined
>obj : { a?: string; b?: string | undefined; }
>a : string | undefined
obj.b = obj.b;
>obj.b = obj.b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
if ('a' in obj) {
>'a' in obj : boolean
>'a' : "a"
>obj : { a?: string; b?: string | undefined; }
obj.a;
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
obj.a = obj.a;
>obj.a = obj.a : string
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
}
else {
obj.a;
>obj.a : undefined
>obj : { a?: string; b?: string | undefined; }
>a : undefined
obj.a = obj.a; // Error
>obj.a = obj.a : undefined
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>obj.a : undefined
>obj : { a?: string; b?: string | undefined; }
>a : undefined
}
if (obj.hasOwnProperty('a')) {
>obj.hasOwnProperty('a') : boolean
>obj.hasOwnProperty : (v: PropertyKey) => boolean
>obj : { a?: string; b?: string | undefined; }
>hasOwnProperty : (v: PropertyKey) => boolean
>'a' : "a"
obj.a;
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
obj.a = obj.a;
>obj.a = obj.a : string
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
}
else {
obj.a;
>obj.a : undefined
>obj : { a?: string; b?: string | undefined; }
>a : undefined
obj.a = obj.a; // Error
>obj.a = obj.a : undefined
>obj.a : string
>obj : { a?: string; b?: string | undefined; }
>a : string
>obj.a : undefined
>obj : { a?: string; b?: string | undefined; }
>a : undefined
}
if ('b' in obj) {
>'b' in obj : boolean
>'b' : "b"
>obj : { a?: string; b?: string | undefined; }
obj.b;
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
obj.b = obj.b;
>obj.b = obj.b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
}
else {
obj.b;
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
obj.b = obj.b;
>obj.b = obj.b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
}
if (obj.hasOwnProperty('b')) {
>obj.hasOwnProperty('b') : boolean
>obj.hasOwnProperty : (v: PropertyKey) => boolean
>obj : { a?: string; b?: string | undefined; }
>hasOwnProperty : (v: PropertyKey) => boolean
>'b' : "b"
obj.b;
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
obj.b = obj.b;
>obj.b = obj.b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
}
else {
obj.b;
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
obj.b = obj.b;
>obj.b = obj.b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
>obj.b : string | undefined
>obj : { a?: string; b?: string | undefined; }
>b : string | undefined
}
}
function f3(obj: Partial<{ a: string, b: string | undefined }>) {
>f3 : (obj: Partial<{ a: string; b: string | undefined; }>) => void
>obj : Partial<{ a: string; b: string | undefined; }>
>a : string
>b : string | undefined
let a = obj.a; // string | undefined
>a : string | undefined
>obj.a : string | undefined
>obj : Partial<{ a: string; b: string | undefined; }>
>a : string | undefined
let b = obj.b; // string | undefined
>b : string | undefined
>obj.b : string | undefined
>obj : Partial<{ a: string; b: string | undefined; }>
>b : string | undefined
obj.a = 'hello';
>obj.a = 'hello' : "hello"
>obj.a : string
>obj : Partial<{ a: string; b: string | undefined; }>
>a : string
>'hello' : "hello"
obj.b = 'hello';
>obj.b = 'hello' : "hello"
>obj.b : string | undefined
>obj : Partial<{ a: string; b: string | undefined; }>
>b : string | undefined
>'hello' : "hello"
obj.a = undefined; // Error
>obj.a = undefined : undefined
>obj.a : string
>obj : Partial<{ a: string; b: string | undefined; }>
>a : string
>undefined : undefined
obj.b = undefined;
>obj.b = undefined : undefined
>obj.b : string | undefined
>obj : Partial<{ a: string; b: string | undefined; }>
>b : string | undefined
>undefined : undefined
}
function f4(t: [string?]) {
>f4 : (t: [string?]) => void
>t : [string?]
let x = t[0]; // string | undefined
>x : string | undefined
>t[0] : string | undefined
>t : [string?]
>0 : 0
t[0] = 'hello';
>t[0] = 'hello' : "hello"
>t[0] : string
>t : [string?]
>0 : 0
>'hello' : "hello"
t[0] = undefined; // Error
>t[0] = undefined : undefined
>t[0] : string
>t : [string?]
>0 : 0
>undefined : undefined
}
function f4a(t1: [number, string?], t2: [number, string?, string?]) {
>f4a : (t1: [number, string?], t2: [number, string?, string?]) => void
>t1 : [number, string?]
>t2 : [number, string?, string?]
t1 = t2; // Wasn't an error, but should be
>t1 = t2 : [number, string?, string?]
>t1 : [number, string?]
>t2 : [number, string?, string?]
}
function f5(t: [number, string?, boolean?]) {
>f5 : (t: [number, string?, boolean?]) => void
>t : [number, string?, boolean?]
t = [42];
>t = [42] : [number]
>t : [number, string?, boolean?]
>[42] : [number]
>42 : 42
t = [42, 'abc'];
>t = [42, 'abc'] : [number, string]
>t : [number, string?, boolean?]
>[42, 'abc'] : [number, string]
>42 : 42
>'abc' : "abc"
t = [42, 'abc', true];
>t = [42, 'abc', true] : [number, string, true]
>t : [number, string?, boolean?]
>[42, 'abc', true] : [number, string, true]
>42 : 42
>'abc' : "abc"
>true : true
t = [42, ,];
>t = [42, ,] : [number, never?]
>t : [number, string?, boolean?]
>[42, ,] : [number, never?]
>42 : 42
> : undefined
t = [42, , ,];
>t = [42, , ,] : [number, never?, never?]
>t : [number, string?, boolean?]
>[42, , ,] : [number, never?, never?]
>42 : 42
> : undefined
> : undefined
t = [42, , , ,]; // Error
>t = [42, , , ,] : [number, never?, never?, never?]
>t : [number, string?, boolean?]
>[42, , , ,] : [number, never?, never?, never?]
>42 : 42
> : undefined
> : undefined
> : undefined
t = [, , true]; // Error
>t = [, , true] : [never?, never?, true?]
>t : [number, string?, boolean?]
>[, , true] : [never?, never?, true?]
> : undefined
> : undefined
>true : true
t = [42, undefined, true]; // Error
>t = [42, undefined, true] : [number, undefined, true]
>t : [number, string?, boolean?]
>[42, undefined, true] : [number, undefined, true]
>42 : 42
>undefined : undefined
>true : true
}
function f6() {
>f6 : () => void
const t1 = [1, 2] as const;
>t1 : readonly [1, 2]
>[1, 2] as const : readonly [1, 2]
>[1, 2] : readonly [1, 2]
>1 : 1
>2 : 2
const t2 = [1, 2, ,] as const;
>t2 : readonly [1, 2, never?]
>[1, 2, ,] as const : readonly [1, 2, never?]
>[1, 2, ,] : readonly [1, 2, never?]
>1 : 1
>2 : 2
> : undefined
const t3 = [1, 2, , ,] as const;
>t3 : readonly [1, 2, never?, never?]
>[1, 2, , ,] as const : readonly [1, 2, never?, never?]
>[1, 2, , ,] : readonly [1, 2, never?, never?]
>1 : 1
>2 : 2
> : undefined
> : undefined
const t4 = [1, , 2] as const;
>t4 : readonly [1, never?, 2?]
>[1, , 2] as const : readonly [1, never?, 2?]
>[1, , 2] : readonly [1, never?, 2?]
>1 : 1
> : undefined
>2 : 2
const t5 = [1, , , 2] as const;
>t5 : readonly [1, never?, never?, 2?]
>[1, , , 2] as const : readonly [1, never?, never?, 2?]
>[1, , , 2] : readonly [1, never?, never?, 2?]
>1 : 1
> : undefined
> : undefined
>2 : 2
}
// Example from #13195
type Props = {
>Props : Props
foo: string;
>foo : string
bar: string
>bar : string
}
type InputProps = {
>InputProps : InputProps
foo?: string;
>foo : string | undefined
bar: string;
>bar : string
}
const defaultProps: Pick<Props, 'foo'> = { foo: 'foo' };
>defaultProps : Pick<Props, "foo">
>{ foo: 'foo' } : { foo: string; }
>foo : string
>'foo' : "foo"
const inputProps: InputProps = { foo: undefined, bar: 'bar' };
>inputProps : InputProps
>{ foo: undefined, bar: 'bar' } : { foo: undefined; bar: string; }
>foo : undefined
>undefined : undefined
>bar : string
>'bar' : "bar"
const completeProps: Props = { ...defaultProps, ...inputProps };
>completeProps : Props
>{ ...defaultProps, ...inputProps } : { foo: string; bar: string; }
>defaultProps : Pick<Props, "foo">
>inputProps : InputProps
// Example from #13195
const t1: [number, string?, boolean?] = [1];
>t1 : [number, string?, boolean?]
>[1] : [number]
>1 : 1
const t2: [number, string?, boolean?] = [1, undefined];
>t2 : [number, string?, boolean?]
>[1, undefined] : [number, undefined]
>1 : 1
>undefined : undefined
const t3: [number, string?, boolean?] = [1, "string", undefined];
>t3 : [number, string?, boolean?]
>[1, "string", undefined] : [number, string, undefined]
>1 : 1
>"string" : "string"
>undefined : undefined
const t4: [number, string?, boolean?] = [1, undefined, undefined];
>t4 : [number, string?, boolean?]
>[1, undefined, undefined] : [number, undefined, undefined]
>1 : 1
>undefined : undefined
>undefined : undefined
// Example from #13195
const x: { foo?: number } = { foo: undefined };
>x : { foo?: number; }
>foo : number | undefined
>{ foo: undefined } : { foo: undefined; }
>foo : undefined
>undefined : undefined
const y: { foo: number } = { foo: 123, ...x };
>y : { foo: number; }
>foo : number
>{ foo: 123, ...x } : { foo: number; }
>foo : number
>123 : 123
>x : { foo?: number; }
// Index signatures and strict optional properties
interface Test {
[key: string]: string;
>key : string
foo?: string; // Should be ok
>foo : string | undefined
bar?: string | undefined; // Error
>bar : string | undefined
}
// Strict optional properties and inference
declare let ox1: { p: string };
>ox1 : { p: string; }
>p : string
declare let ox2: { p: string | undefined };
>ox2 : { p: string | undefined; }
>p : string | undefined
declare let ox3: { p?: string };
>ox3 : { p?: string; }
>p : string | undefined
declare let ox4: { p?: string | undefined };
>ox4 : { p?: string | undefined; }
>p : string | undefined
declare let tx1: [string];
>tx1 : [string]
declare let tx2: [string | undefined];
>tx2 : [string | undefined]
declare let tx3: [string?];
>tx3 : [string?]
declare let tx4: [(string | undefined)?];
>tx4 : [(string | undefined)?]
declare function f11<T>(x: { p?: T }): T;
>f11 : <T>(x: { p?: T;}) => T
>x : { p?: T; }
>p : T | undefined
f11(ox1); // string
>f11(ox1) : string
>f11 : <T>(x: { p?: T; }) => T
>ox1 : { p: string; }
f11(ox2); // string | undefined
>f11(ox2) : string | undefined
>f11 : <T>(x: { p?: T; }) => T
>ox2 : { p: string | undefined; }
f11(ox3); // string
>f11(ox3) : string
>f11 : <T>(x: { p?: T; }) => T
>ox3 : { p?: string; }
f11(ox4); // string | undefined
>f11(ox4) : string | undefined
>f11 : <T>(x: { p?: T; }) => T
>ox4 : { p?: string | undefined; }
declare function f12<T>(x: [T?]): T;
>f12 : <T>(x: [T?]) => T
>x : [T?]
f12(tx1); // string
>f12(tx1) : string
>f12 : <T>(x: [T?]) => T
>tx1 : [string]
f12(tx2); // string | undefined
>f12(tx2) : string | undefined
>f12 : <T>(x: [T?]) => T
>tx2 : [string | undefined]
f12(tx3); // string
>f12(tx3) : string
>f12 : <T>(x: [T?]) => T
>tx3 : [string?]
f12(tx4); // string | undefined
>f12(tx4) : string | undefined
>f12 : <T>(x: [T?]) => T
>tx4 : [(string | undefined)?]
declare function f13<T>(x: Partial<T>): T;
>f13 : <T>(x: Partial<T>) => T
>x : Partial<T>
f13(ox1); // { p: string }
>f13(ox1) : { p: string; }
>f13 : <T>(x: Partial<T>) => T
>ox1 : { p: string; }
f13(ox2); // { p: string | undefined }
>f13(ox2) : { p: string | undefined; }
>f13 : <T>(x: Partial<T>) => T
>ox2 : { p: string | undefined; }
f13(ox3); // { p: string }
>f13(ox3) : { p: string; }
>f13 : <T>(x: Partial<T>) => T
>ox3 : { p?: string; }
f13(ox4); // { p: string | undefined }
>f13(ox4) : { p: string | undefined; }
>f13 : <T>(x: Partial<T>) => T
>ox4 : { p?: string | undefined; }
f13(tx1); // [string]
>f13(tx1) : [string]
>f13 : <T>(x: Partial<T>) => T
>tx1 : [string]
f13(tx2); // [string | undefined]
>f13(tx2) : [string | undefined]
>f13 : <T>(x: Partial<T>) => T
>tx2 : [string | undefined]
f13(tx3); // [string]
>f13(tx3) : [string]
>f13 : <T>(x: Partial<T>) => T
>tx3 : [string?]
f13(tx4); // [string | undefined]
>f13(tx4) : [string | undefined]
>f13 : <T>(x: Partial<T>) => T
>tx4 : [(string | undefined)?]
// Repro from #44388
type Undefinable<T> = T | undefined;
>Undefinable : Undefinable<T>
function expectNotUndefined<T>(value: Undefinable<T>): T {
>expectNotUndefined : <T>(value: Undefinable<T>) => T
>value : Undefinable<T>
if (value === undefined) {
>value === undefined : boolean
>value : Undefinable<T>
>undefined : undefined
throw new TypeError('value is undefined');
>new TypeError('value is undefined') : TypeError
>TypeError : TypeErrorConstructor
>'value is undefined' : "value is undefined"
}
return value;
>value : T
}
interface Bar {
bar?: number;
>bar : number | undefined
}
function aa(input: Bar): void {
>aa : (input: Bar) => void
>input : Bar
const notUndefinedVal = expectNotUndefined(input.bar);
>notUndefinedVal : number
>expectNotUndefined(input.bar) : number
>expectNotUndefined : <T>(value: Undefinable<T>) => T
>input.bar : number | undefined
>input : Bar
>bar : number | undefined
bb(notUndefinedVal);
>bb(notUndefinedVal) : void
>bb : (input: number) => void
>notUndefinedVal : number
}
declare function bb(input: number): void;
>bb : (input: number) => void
>input : number
interface U1 {
name: string
>name : string
email?: string | number | undefined
>email : string | number | undefined
}
interface U2 {
name: string
>name : string
email?: string | number
>email : string | number | undefined
}
declare const e: string | boolean | undefined
>e : string | boolean | undefined
declare const u1: U1
>u1 : U1
declare let u2: U2
>u2 : U2
u1.email = e // error, but only because boolean isn't in email's type
>u1.email = e : string | boolean | undefined
>u1.email : string | number | undefined
>u1 : U1
>email : string | number | undefined
>e : string | boolean | undefined
u2.email = e // error, and suggest adding undefined
>u2.email = e : string | boolean | undefined
>u2.email : string | number
>u2 : U2
>email : string | number
>e : string | boolean | undefined
u2 = {
>u2 = { name: 'hi', email: undefined} : { name: string; email: undefined; }
>u2 : U2
>{ name: 'hi', email: undefined} : { name: string; email: undefined; }
name: 'hi',
>name : string
>'hi' : "hi"
email: undefined
>email : undefined
>undefined : undefined
}
// Repro from #44437
declare var a: {[x: string]: number | string }
>a : { [x: string]: string | number; }
>x : string
declare var b: {a: number, b: string}
>b : { a: number; b: string; }
>a : number
>b : string
declare var c: {a: number, b?: string}
>c : { a: number; b?: string; }
>a : number
>b : string | undefined
declare var d: {a: number, b: string | undefined }
>d : { a: number; b: string | undefined; }
>a : number
>b : string | undefined
declare var e: {a: number, b?: string | undefined }
>e : { a: number; b?: string | undefined; }
>a : number
>b : string | undefined
a = b;
>a = b : { a: number; b: string; }
>a : { [x: string]: string | number; }
>b : { a: number; b: string; }
a = c;
>a = c : { a: number; b?: string; }
>a : { [x: string]: string | number; }
>c : { a: number; b?: string; }
a = d; // Error
>a = d : { a: number; b: string | undefined; }
>a : { [x: string]: string | number; }
>d : { a: number; b: string | undefined; }
a = e; // Error
>a = e : string | boolean | undefined
>a : { [x: string]: string | number; }
>e : string | boolean | undefined
// Repro from #46004
interface PropsFromReact {
onClick?: () => void;
>onClick : (() => void) | undefined
}
interface PropsFromMaterialUI {
onClick?: (() => void) | undefined;
>onClick : (() => void) | undefined
}
type TheTypeFromMaterialUI = PropsFromReact & PropsFromMaterialUI;
>TheTypeFromMaterialUI : TheTypeFromMaterialUI
interface NavBottomListItem extends TheTypeFromMaterialUI {
value: string;
>value : string
}
// Repro from #46004
type UA = undefined; // Explicit undefined type
>UA : undefined
type UB = { x?: never }['x']; // undefined from missing property
>UB : undefined
>x : undefined
type UC = UA & UB; // undefined
>UC : undefined