Comments (8)
I can see that but it also means that the P[K] & {} being assignable to S[K] (something that is allowed today) is already speculative too, right?
Well, it's allowed only because of the oddity of Record<string, any>
constraints (see my comment).
from typescript.
Simpler repro:
function f1<T extends Record<string, any>, K extends keyof T>(x: T[K] | undefined) {
if (x === undefined) return;
x; // T[K] & ({} | null)
if (x === undefined) return;
x; // T[K] & {}
}
from typescript.
In addition to the odd narrowing behavior demonstrated by the OP and the simplified repro above, we also have inconsistencies in type relationships involving intersections that strip undefined
, null
, or both:
function f2<T, K extends keyof T>(t: T[K], p1: Partial<T>[K] & {}, p2: Partial<T>[K] & ({} | null)) {
t = p1;
t = p2; // Unexpected error
}
The issue here is missing normalization of intersections in certain cases. Specifically, we only normalize intersections with {}
, not intersections with null
or undefined
.
from typescript.
@ahejlsberg that feels like an answer to this comment, right? I mean, this extra observed problem would fix what has been described there.
Do you plan to work on fixing this? Or should I try to extend my PR with a fix for this?
from typescript.
Furthermore, using Record<string, any>
as a constraint exhibits some odd behavior:
function f3<T, P extends Record<string, any>>(t: T[keyof T], p1: P[keyof P], p2: P[keyof P] & {}) {
t = p1; // Error as expected
t = p2; // Missing error
}
function f4<T, P extends Record<string, unknown>>(t: T[keyof T], p1: P[keyof P], p2: P[keyof P] & {}) {
t = p1; // Error as expected
t = p2; // Error as expected
}
This has to do with the constraint of P[keyof P]
being any
which effectively circumvents type checking in some cases. In general, it seems suspicious for any instantiable type to have a constraint of any
, and we do indeed ignore such constraints in places. Just not everywhere.
from typescript.
@ahejlsberg that feels like an answer to #57692 (comment), right? I mean, this extra observed problem would fix what has been described there.
Given type parameters S
and K extends keyof S
, I would expect Partial<S>[K] & ({} | null)
to be assignable to S[K]
. However, when P extends Partial<S>
, I think expecting P[K] & ({} | null)
to be assignable to S[K]
is getting speculative.
Do you plan to work on fixing this? Or should I try to extend my PR with a fix for this?
I will be putting up a PR that fixes the issues demonstrated by f1
and f2
above.
from typescript.
However, when
P extends Partial<S>
, I think expectingP[K] & ({} | null)
to be assignable toS[K]
is getting speculative.
I can see that but it also means that the P[K] & {}
being assignable to S[K]
(something that is allowed today) is already speculative too, right?
from typescript.
It has been called an oddity but I'm not sure if I should interpret this as "odd but working as intended" or "odd and it could be fixed" 😅 In general, I interpret your comments about this here as the latter but I'm not 100% sure.
from typescript.
Related Issues (20)
- HTMLFormElement disallows symbol keys HOT 5
- TypeScript language service cannot find subclass references/implementation of mixin methods
- when using ts.getJSDocTags, the value of @type is not returned. Is there any solution? HOT 2
- Compiler allows narrower method signature than implemented interface HOT 7
- Allow overload signatures to have different access levels HOT 3
- Watcher recursively watches irrelevant directories HOT 11
- Auto-closing of tags within curly braces `{}` does not work when parent element is same tag in JSX HOT 1
- Undocumented breaking change in 5.5.0-beta for reference directives HOT 3
- 5.5.0 regression - importHelpers do not work with moduleResolution: bundler HOT 1
- 5.5.0 inheriting outDir: ${configDir} does not automatically exclude it from compilation HOT 3
- isolatedDeclarations wrongly enabled in VSCode HOT 3
- ESNext Set methods HOT 1
- isolatedDeclarations should not have warning for functions that have no return statements HOT 4
- Trivia ownership documentation seems to be incorrect
- `--isolatedDeclarations` allows generator functions HOT 1
- Allow `--noCheck` on the CLI with top-level `--build`
- Union in template literal simplifying unexpectedly HOT 2
- Default import from an ESM package into a CommonJS project with esModuleInterop is faulty
- Watch cannot handle large amount of file changes HOT 1
- generator next type should be inferred as union (instead of intersection) of yields' types OR just unknown
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typescript.