1

This question might already be answered somewhere in this somewhat similar question, however the example code and explanations are a very verbose and I can't really seem to distill it down the useful parts.

I am hoping someone can provide an explanation as to why the following code doesn't produce a type error on the indicated line. Is there any utility type I can use which would produce the result I want?

Playground

type BaseMessage = { foo: string }

type JobMessage = BaseMessage & { bar: number }

const processBase = (msg: BaseMessage) => {}

const processJob = (msg: JobMessage) => {
  // I expect this next line to error
  processBase(msg);
  // This produces the error I am hoping for
  processBase({ foo: 'str', bar: 1234 });
}
Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
  • 1
    `processBase` doesn't care if you provided extra properties. After all, it's not supposed to use them... – kelsny Oct 05 '22 at 19:30
  • 2
    This doesn't have much to do with intersections but with [excess property checks](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html#stricter-object-literal-assignment-checks), which only get triggered for object literals (and only in certain contexts). Since `msg` is not an object literal, excess property checks don't occur. – jcalz Oct 05 '22 at 19:32
  • Well, you could add a check like [this](https://tsplay.dev/WkkA2W), but it will be really annoying to work with `msg` in the body of `processBase`. – kelsny Oct 05 '22 at 19:32
  • The link should be updated now. @caTS - I get that `processBase` doesn't use the extra properties, but in the second invocation in the example code, I pass extra properties and I get the type error I want: "bar does not exist on BaseMessage". – Ryan Wheale Oct 05 '22 at 19:33
  • 1
    _Not_ erroring on the excess properties is awesome, BTW. It's really common to define only what a function cares about and then pass in something bigger that conforms to that. https://www.typescriptlang.org/play?ts=4.5.5#code/MYewdgzgLgBArhApgJxgXhgbxgSwCYBcMA5AigLQCMATAMzEA0MUAngA6JGlLKMxgBDALacSAMRAgYAWWAAhAbxgBfALAAoUJFgAjSQGt0WXIRJ6Q+8gBYArADY+rDl3P7HOKABtRxaSB0sMAAiOMBuKhoaAGZwYMBQOOAweIjeUIgASoigyHgAFMjZILlE2PhE0Mg4YADmTE6ildU1KgCUWBowMAD03ck6AHQ1iFAAKgI63nkNrQMpaYh5+O29MMUwECAiUAAWzQMaauoa8yOZRbl5ZMgrfVHViCepZ1k5+a63MPdgiEA – Alex Wayne Oct 05 '22 at 19:35
  • @jcalz - can you post your explanation in an answer, I'll accept it. Also, is it possible to have a utility which can help achieve what I'm needing? If not, please say so in your answer. – Ryan Wheale Oct 05 '22 at 19:36
  • Using the `Exactly` helper type from [here](https://stackoverflow.com/questions/69647392/extend-and-only-specify-known-properties) gives you [this](https://tsplay.dev/Wy6ndw), but it's always possible to circumvent with enough ingenuity on the part of the determined caller. You should probably just make sure that your `processBase()` *does not care* about excess properties – jcalz Oct 05 '22 at 19:43
  • @jcalz - the last example you provided is exactly what I'm looking for, thanks. I feel like the links you provided are still very verbose and over-indulged. I'm just trying to show a distilled problem/solution. Can you please provide your playground code as an answer - it makes it very easy to see the solution and it's caveats (unlike the other solutions you reference). – Ryan Wheale Oct 05 '22 at 19:52
  • 2
    ". I feel like the links you provided are still very verbose and over-indulged" Well since I wrote those you're probably going to get more of the same if you ask me for it. Maybe someone else can help you? This question is already closed as a duplicate though, so feel free to write up an answer of your own to one or more of those questions if you feel the answers are too meandering. – jcalz Oct 05 '22 at 19:53

0 Answers0