Skip to content
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 operator breaks with callback on Partial object literals #55803

Closed
JDMathew opened this issue Sep 20, 2023 · 5 comments
Closed

satisfies operator breaks with callback on Partial object literals #55803

JDMathew opened this issue Sep 20, 2023 · 5 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@JDMathew
Copy link

JDMathew commented Sep 20, 2023

πŸ”Ž Search Terms

"satisfies", "callback", "function"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried (above 4.8), and I reviewed the FAQ for entries about "Bugs that Aren't Bugs"

⏯ Playground Link

Link to playground

πŸ’» Code

type AuthState = {
  isLoading: boolean;
  isLoggedIn: boolean;
  userToken: string | null;
};

type ActionFunction = (arg: any) => {
  type: string;
  payload: Prettify<Partial<AuthState>>;
};

export const authActions = {
  signOut: () => ({
    type: actionTypes.SIGN_OUT,
    payload: { userToken: null, isLoggedIn: false },
  }),
  login: ({ userToken }: { userToken: string }) => ({
    type: actionTypes.LOGIN,
    payload: { userToken, isLoggedIn: true },
  }),
  restoreToken: ({ userToken }: { userToken: string }) => ({
    type: 22, // error on type for 22: Type 'number' is not assignable to type 'string'.
    payload: { userToken, isLoading: false, notAValidKey: 'Value' }, // no error on notAValidKey, should error Object literal may only specify known properties, and 'notAValidKey' does not exist in type 'Partial<AuthState>'
  }),
} satisfies Record<string, ActionFunction>;

πŸ™ Actual behavior

There is no error thrown on payload for the key notAValidKey as one would expect since this key isn't inside the Partial type AuthState. There is an error thrown for type with value 22 so the callback type ActionFunction isn't breaking the satisfies operator.

πŸ™‚ Expected behavior

This should throw an error on restoreToken in the above authActions const.
The behaviour should mimic what happens when there is no callback in the object. For example as it errors here:

type AuthState = {
  isLoading: boolean;
  isLoggedIn: boolean;
  userToken: string | null;
};


export const action = {
  key: {
    isLoggedIn: true,
    notAValidKey: 'Value', // error thrown: Object literal may only specify known properties, and 'notAValidKey' does not exist in type 'Partial<AuthState>'.
  },
} satisfies Record<string, Partial<AuthState>>;

Additional information about the issue

No response

@fatcerberus
Copy link

Functions aren’t contextually typed in their return type afaik so EPC doesn’t apply. Note that the excess property check is more of a built-in lint rule than a type check, so it’s intentionally not comprehensive.

@fatcerberus
Copy link

fatcerberus commented Sep 20, 2023

Simplified repro (Playground):

type AuthState = {
  isLoading: boolean;
  isLoggedIn: boolean;
  userToken: string | null;
};

type ActionFunction = (arg: any) => {
  type: string;
  payload: Partial<AuthState>;
};

const action1 = (({ userToken }: { userToken: string }) => ({
  type: "fun",
  payload: { userToken, isLoading: false, notAValidKey: 'Value' },
})) satisfies ActionFunction;  // no EPC error

const action2: ActionFunction = ({ userToken }: { userToken: string }) => ({
  type: "fun",
  payload: { userToken, isLoading: false, notAValidKey: 'Value' },
});  // also no EPC error

which I'm almost positive is a duplicate of like 10 other issues (latest I can find: #54661). tl;dr you shouldn't rely on the excess property check to enforce runtime invariants - you need #12936 for that.

@fatcerberus
Copy link

The closest thing to a canonical duplicate afaict is #7547

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Sep 26, 2023
@RyanCavanaugh
Copy link
Member

#241 is also relevant

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Not a Defect This behavior is one of several equally-correct options
Projects
None yet
Development

No branches or pull requests

4 participants