Closed
Description
π Search Terms
regression mapped type generic intersection undefined optional
π Version & Regression Information
- This changed in commit or PR #57549
β― Playground Link
π» Code
import {z} from 'zod';
const schema = z.object({
prop: z.string(),
});
{
type DerivedType = z.infer<typeof schema>;
type BadData = { id: string } & DerivedType;
function badExample<K extends keyof BadData>(data: Pick<Pick<BadData, K | 'id'>, K>): Pick<BadData, K> {
return data;
// ^^^^^^ Type 'Pick<Pick<Data, K | "id">, K>' is not assignable to type 'Pick<Data, K>'.
// Type 'Data[P] | undefined' is not assignable to type 'Data[P]'.
// Type 'undefined' is not assignable to type 'Data[P]'.
// Type 'undefined' is not assignable to type 'string'.(2322)
}
}
{
type ExplicitType = {
prop: string;
}
type GoodData = { id: string } & ExplicitType;
function goodExample<K extends keyof GoodData>(data: Pick<Pick<GoodData, K | 'id'>, K>): Pick<GoodData, K> {
return data;
}
}
π Actual behavior
Type error
π Expected behavior
No type error. DerivedType
expands to ExplicitType
, yet produces different results.
Additional information about the issue
The title of this issue is probably inaccurate/misleading. I just wasn't sure how to describe the behavior. Note that I discovered this while using Airtable's internal schema lib, yet fortunately I was also able to reproduce this with Zod despite the implementations of the infer
type being entirely different.
I bisected this to this commit 3b1b82a with @ahejlsberg's PR #57549
every-ts switch 309fd3db81955ef7a4dd55a80e333b2b767717a7
remote: Enumerating objects: 259180, done.
remote: Counting objects: 100% (379/379), done.
remote: Compressing objects: 100% (316/316), done.
remote: Total 259180 (delta 148), reused 230 (delta 41), pack-reused 258801
Receiving objects: 100% (259180/259180), 908.24 MiB | 7.64 MiB/s, done.
Resolving deltas: 100% (154585/154585), done.
remote: Enumerating objects: 868, done.
remote: Counting objects: 100% (847/847), done.
remote: Compressing objects: 100% (394/394), done.
remote: Total 868 (delta 486), reused 668 (delta 453), pack-reused 21
Receiving objects: 100% (868/868), 3.10 MiB | 10.90 MiB/s, done.
Resolving deltas: 100% (495/495), done.
Updating files: 100% (898/898), done.
Previous HEAD position was e5bf594753 Infer type predicates from function bodies using control flow analysis (#57465)
HEAD is now at 309fd3db81 Revert PR 56161 (#57853)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect bad
You need to start by "git bisect start"
Do you want me to do it for you [Y/n]? y
status: waiting for both good and bad commits
status: waiting for good commit(s), bad commit known
$ every-ts bisect good v5.4.2
Bisecting: a merge base must be tested
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (2/2), 76.47 KiB | 2.64 MiB/s, done.
[d04e3489b0d8e6bc9a8a9396a633632a5a467328] Improve apparent type of mapped types (#57122)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect good
Bisecting: 52 revisions left to test after this (roughly 6 steps)
remote: Enumerating objects: 207, done.
remote: Counting objects: 100% (185/185), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 207 (delta 141), reused 128 (delta 128), pack-reused 22
Receiving objects: 100% (207/207), 1.06 MiB | 6.50 MiB/s, done.
Resolving deltas: 100% (153/153), done.
[353ccb7688351ae33ccf6e0acb913aa30621eaf4] Ensure correct script kind and text when using cached sourceFile from scriptInfo (#57641)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect bad
Bisecting: 26 revisions left to test after this (roughly 5 steps)
remote: Enumerating objects: 253, done.
remote: Counting objects: 100% (230/230), done.
remote: Compressing objects: 100% (75/75), done.
remote: Total 253 (delta 163), reused 155 (delta 155), pack-reused 23
Receiving objects: 100% (253/253), 604.74 KiB | 8.28 MiB/s, done.
Resolving deltas: 100% (175/175), done.
[a77370342dcdbd9273fe1716390d90a9b0d88fcc] Close "Design Limitation" automatically (#57554)
Building TypeScript...
announce
TypeScript built successfully!
$ announce
$ every-ts bisect good ; announce
Bisecting: 13 revisions left to test after this (roughly 4 steps)
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 7 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (7/7), 882.83 KiB | 5.38 MiB/s, done.
[877d9d316dd69ebd8253fe4c8915800415b0f455] Intl.NumberFormat: Add latest options, fix previous library discrepancies (#56902)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect good ; announce
Bisecting: 6 revisions left to test after this (roughly 3 steps)
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 550.26 KiB | 5.79 MiB/s, done.
[1d6d962d3132a901f5fb48be4a389c45faf5a74e] Update package-lock.json
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect good ; announce
Bisecting: 3 revisions left to test after this (roughly 2 steps)
[320e17f1225e1a4f8fcf65554fe0ba2405d8a27f] "Annotate" exported object to fix named / namespace imports of our API in Node ESM (#57133)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect good ; announce
Bisecting: 1 revision left to test after this (roughly 1 step)
[3b1b82a6bf9267b4c99cbd8c4f25a3e578da0d44] Add optionality to mapped type indexed access substitutions (#57549)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect bad ; announce
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[8336042ea3f84ad536a190ea75e47e74414e8081] Bump the github-actions group with 2 updates (#57624)
Building TypeScript...
TypeScript built successfully!
$ every-ts bisect good ; announce
3b1b82a6bf9267b4c99cbd8c4f25a3e578da0d44 is the first bad commit