-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
satisfies
changes the generic type, "resolves" it immediately
#52394
Comments
That's weird, but also, what reason would you write this code in the first place? Something of type |
@RyanCavanaugh type MyType = {
a: string;
b: 'a' | 'b' | 'c' | 'd' | 'e';
};
const foo = <T extends 'a' | 'b' | 'c'>(bar: T) => ({
a: bar,
b: bar,
}) satisfies MyType;
// I should now have the return type be {a: T; b: t},
// (but instead it's {a: 'a' | 'b' | 'c'; b: 'a' | 'b' | 'c'}, as if it was resolved immediately)
// while also being sure that if any API changes (like MyType) in the future, I will know exactly what needs to change What's worth noting is that this bug seems to only happen in some scenarios of type MyType = {
a: string;
b: string;
};
const foo = <T extends string>(bar: T) => ({
a: bar,
b: bar,
}) satisfies MyType;
const result = foo('abc')
// ^? {a: 'abc'; b: 'abc'} |
It's this call to The simplest possible fix that comes to my mind is to just avoid this "resolving" when we are |
Uh, I have no idea. It's going to be sketchy to try to change this because we don't have much real-world coverage on |
Interestingly, a similar thing happens for auto types: const foo = <T extends 1 | 2>(bar: T) => {
let test1
test1 = bar
test1 // actual: `1 | 2`, expected: `T extends 1 | 2`
} |
@Andarist just tested the auto types you just mentioned on different versions of ts on the playground. It works correctly on v4.2.3 (type is If that helps |
It makes sense since this |
I think I stumbled on the same case: type BoxState = 'open' | 'closed'
type Box = {
boxState: BoxState;
boxedObject: unknown
}
function boxFactorySafe<BS extends BoxState>(boxState: BS, boxedObject: unknown) {
return {
boxState,
boxedObject
} as const satisfies Box;
}
const safeBoxedObject = boxFactorySafe(
'open',
'some value'
)
// Tests
type testCasesSafe = [
// Fails because satisfies "destroys" the boxState const value -- why?
Expect<Equal<typeof safeBoxedObject['boxState'], 'open'>>
] |
It definitely looks similar, I verified that this |
Is this another example? Slightly different because type Obj<S extends string> = { s: S };
const thing = <S extends string>(o: Obj<S>) => {
return o;
};
const yay = thing({ s: "hi" });
// ^? const yay: Obj<"hi">
const hmm = thing({ s: "hi" }) satisfies Obj<string>;
// ^? const hmm: Obj<string> Admittedly, the above is an absolutely contrived example and does not differ from type Str<S extends string> = S;
const thing = <S extends string>(o: Str<S>) => {
return o;
};
const yay = thing("hi");
// ^? const yay: "hi"
const alsoYay = thing("hi") satisfies Str<string>;
// ^? const alsoYay: "hi" From the docs, my understanding of |
I just ran into something that feels very similar, where using type Foo = { a: boolean; }
const f = {a: true};
f.a = false; // no problem!
const g = {a: true} satisfies Foo;
g.a = false; // uh oh
//^ Type 'false' is not assignable to type 'true'. I filed this as #55189, but feel free to close if it's a duplicate |
The issue that you filed feels different than this one to me. |
Bug Report
It seems that using
satisfies
on a value that is bound to a generic type, in some way resolves the generic type at that place.Playground link
🔎 Search Terms
satisfies
changes type, generic, widening🕗 Version & Regression Information
Using 4.9.4 now with
satisfies
and noticed this.⏯ Playground Link
Playground link
🙁 Actual behavior
a
andb
have different types as seen in the playground🙂 Expected behavior
satisfies
should be a no-opThe text was updated successfully, but these errors were encountered: