Skip to content

Commit 602ca72

Browse files
committed
add test case
1 parent 5566306 commit 602ca72

File tree

5 files changed

+167
-486
lines changed

5 files changed

+167
-486
lines changed

tests/baselines/reference/narrowUnionOfObjectsByPrimitiveProperty.errors.txt

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ narrowUnionOfObjectsByPrimitiveProperty.ts(70,1): error TS2322: Type '{ prop: st
1111
Type 'string | number' is not assignable to type 'number'.
1212
Type 'string' is not assignable to type 'number'.
1313
narrowUnionOfObjectsByPrimitiveProperty.ts(73,14): error TS2550: Property 'repeat' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.
14-
narrowUnionOfObjectsByPrimitiveProperty.ts(98,32): error TS2339: Property 'label' does not exist on type 'never'.
14+
narrowUnionOfObjectsByPrimitiveProperty.ts(96,32): error TS2339: Property 'label' does not exist on type 'never'.
1515

1616

1717
==== narrowUnionOfObjectsByPrimitiveProperty.ts (6 errors) ====
@@ -127,72 +127,11 @@ narrowUnionOfObjectsByPrimitiveProperty.ts(98,32): error TS2339: Property 'label
127127
declare const opt: Opt
128128

129129
if (typeof opt.label === 'string') {
130-
opt
131-
// ^?
132130
const l = opt.label;
133131
const a = opt.alias ?? opt.label;
134132
~~~~~
135133
!!! error TS2339: Property 'label' does not exist on type 'never'.
136134
} else {
137-
opt
138-
// ^?
139135
const l = opt.label;
140136
const a = opt.alias ?? opt.label.original;
141-
}
142-
143-
144-
type PackageDetails = {
145-
docsLink?: string;
146-
docsLinkWarning?: string;
147-
title?: string;
148-
description?: string;
149-
repo?: string;
150-
license?: string;
151-
};
152-
153-
type PackageDetailsSuccess = PackageDetails & {
154-
docsLink: string;
155-
};
156-
157-
interface FilePathAndName {
158-
path: string;
159-
name: string;
160-
}
161-
162-
interface PackageFilePathAndName extends FilePathAndName {
163-
packageRegistry: string; // e.g. npm, pypi
164-
}
165-
166-
type ParsedPackageInfo = {
167-
name: string;
168-
packageFile: PackageFilePathAndName;
169-
language: string;
170-
version: string;
171-
};
172-
173-
174-
type PackageDocsResult = {
175-
packageInfo: ParsedPackageInfo;
176-
} & ({
177-
error: string;
178-
details?: never;
179-
} | {
180-
details: PackageDetailsSuccess;
181-
error?: never;
182-
})
183-
184-
declare const filtered: PackageDocsResult[];
185-
186-
filtered.sort((a, b) => {
187-
const rank = (result: PackageDocsResult) => {
188-
result.details
189-
if (result.error) {
190-
return 2;
191-
} else if (result.details?.docsLinkWarning) {
192-
return 1;
193-
} else {
194-
return 0;
195-
}
196-
};
197-
return rank(a) - rank(b);
198-
});
137+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//// [tests/cases/compiler/narrowUnionOfObjectsByPrimitiveProperty.ts] ////
2+
3+
//// [narrowUnionOfObjectsByPrimitiveProperty.ts]
4+
export {}
5+
6+
interface State<Type> {
7+
state: Type;
8+
}
9+
10+
interface UserName {
11+
first: string;
12+
last?: string;
13+
}
14+
15+
const nameState = {} as {
16+
value: string;
17+
state: State<string>;
18+
} | {
19+
value: UserName;
20+
state: State<UserName>;
21+
}
22+
23+
if (typeof nameState.value === "string") {
24+
nameState.state satisfies State<string>;
25+
} else {
26+
nameState.state satisfies State<UserName>;
27+
}
28+
29+
30+
declare const arr: [string, number] | [number, string];
31+
if (typeof arr[0] === "string") {
32+
arr[1] satisfies number;
33+
} else {
34+
arr[1] satisfies string;
35+
}
36+
37+
38+
function aStringOrANumber<T extends { a: string } | { a: number }>(param: T): T extends { a: string } ? string : T extends { a: number } ? number : never {
39+
if (typeof param.a === "string") {
40+
return param.a.repeat(3);
41+
}
42+
if (typeof param.a === "number") {
43+
return Math.exp(param.a);
44+
}
45+
throw new Error()
46+
}
47+
48+
aStringOrANumber({ a: "string" })
49+
aStringOrANumber({ a: 42 })
50+
51+
52+
// The following two tests ensure that the discriminativeness of property 'prop'
53+
// is treated differently in assignability and narrowing, and that the discriminativeness is properly cached.
54+
declare let obj: { prop: string, other: string } | { prop: number, other: number }
55+
56+
// Here, we first perform narrowing, but the subsequent assignability should not be affected.
57+
// We expect an error there because of an incorrect value assigned to 'prop'.
58+
// See contextualTypeWithUnionTypeObjectLiteral.ts
59+
if(typeof obj.prop === "string") {
60+
obj.other.repeat(3);
61+
} else {
62+
Math.exp(obj.other);
63+
}
64+
65+
obj = { prop: Math.random() > 0.5 ? "whatever" : 42, other: "irrelevant" as never }
66+
67+
68+
declare let obj2: { prop: string, other: string } | { prop: number, other: number }
69+
70+
// Here, we first assign a value to 'obj2' and then perform narrowing.
71+
// We expect an error here because of an incorrect value assigned to 'prop', like above,
72+
// but the subsequent narrowing should not be affected by the assignability.
73+
obj2 = { prop: Math.random() > 0.5 ? "whatever" : 42, other: "irrelevant" as never }
74+
75+
if(typeof obj2.prop === "string") {
76+
obj2.other.repeat(3);
77+
} else {
78+
Math.exp(obj2.other);
79+
}
80+
81+
82+
interface ILocalizedString {
83+
original: string;
84+
value: string;
85+
}
86+
87+
type Opt = ({
88+
label: ILocalizedString;
89+
alias?: string;
90+
} | {
91+
label: string;
92+
alias: string;
93+
})
94+
95+
declare const opt: Opt
96+
97+
if (typeof opt.label === 'string') {
98+
const l = opt.label;
99+
const a = opt.alias ?? opt.label;
100+
} else {
101+
const l = opt.label;
102+
const a = opt.alias ?? opt.label.original;
103+
}
104+
105+
//// [narrowUnionOfObjectsByPrimitiveProperty.js]
106+
"use strict";
107+
var _a, _b;
108+
Object.defineProperty(exports, "__esModule", { value: true });
109+
var nameState = {};
110+
if (typeof nameState.value === "string") {
111+
nameState.state;
112+
}
113+
else {
114+
nameState.state;
115+
}
116+
if (typeof arr[0] === "string") {
117+
arr[1];
118+
}
119+
else {
120+
arr[1];
121+
}
122+
function aStringOrANumber(param) {
123+
if (typeof param.a === "string") {
124+
return param.a.repeat(3);
125+
}
126+
if (typeof param.a === "number") {
127+
return Math.exp(param.a);
128+
}
129+
throw new Error();
130+
}
131+
aStringOrANumber({ a: "string" });
132+
aStringOrANumber({ a: 42 });
133+
// Here, we first perform narrowing, but the subsequent assignability should not be affected.
134+
// We expect an error there because of an incorrect value assigned to 'prop'.
135+
// See contextualTypeWithUnionTypeObjectLiteral.ts
136+
if (typeof obj.prop === "string") {
137+
obj.other.repeat(3);
138+
}
139+
else {
140+
Math.exp(obj.other);
141+
}
142+
obj = { prop: Math.random() > 0.5 ? "whatever" : 42, other: "irrelevant" };
143+
// Here, we first assign a value to 'obj2' and then perform narrowing.
144+
// We expect an error here because of an incorrect value assigned to 'prop', like above,
145+
// but the subsequent narrowing should not be affected by the assignability.
146+
obj2 = { prop: Math.random() > 0.5 ? "whatever" : 42, other: "irrelevant" };
147+
if (typeof obj2.prop === "string") {
148+
obj2.other.repeat(3);
149+
}
150+
else {
151+
Math.exp(obj2.other);
152+
}
153+
if (typeof opt.label === 'string') {
154+
var l = opt.label;
155+
var a = (_a = opt.alias) !== null && _a !== void 0 ? _a : opt.label;
156+
}
157+
else {
158+
var l = opt.label;
159+
var a = (_b = opt.alias) !== null && _b !== void 0 ? _b : opt.label.original;
160+
}

0 commit comments

Comments
 (0)