0

So I'm just playing with types in typescript. I'd like to use a type that accepts any type that has only one property (with any type, and any name).

const myWeirdMethod = <T>(t:TypeWithOnlyOneField<T>)=> {
  let numFields = 0
  for(const key in t){
     numFields++
  }
  assert(numFields === 1)
}
caeus
  • 3,084
  • 1
  • 22
  • 36
  • 1
    Could you describe what your use case is? – MaartenDev Nov 16 '21 at 19:02
  • Note that there is absolutely no way to write a type function that corresponds exactly to your implementation: types in TypeScript are open (so values may have more properties than the compiler knows about); the compiler doesn't know about "enumerable" or "own" properties so it can't tell whether a key will really be there at runtime: optional properties are a thing in TS but not JS so anything you do will be wrong sometimes, etc. etc. You can ask TS if a type has exactly one known key like [this](https://tsplay.dev/wEGvVm), but there are so many caveats that fail to match your impl. – jcalz Nov 16 '21 at 21:21
  • If you want I can write up an answer explaining how that works and why you can't get this exact functionality. Let me know. But I don't quite get the use case... why do you care about the exact number of keys an object has at runtime? It's not really the sort of thing that TypeScript enables, so maybe I'm just not seeing the use of it. – jcalz Nov 16 '21 at 21:22

1 Answers1

-1

Using the solution of @jcalz in https://stackoverflow.com/a/53505207/379923 you can get a tuple type with the object keys. Then check the tuple length in TypeWithOnlyOneField, if element [1] is present (there is more than one properties) then "return" never (this will trigger compile time error).

type TypeWithOnlyOneField<T> = UnionToTuple<keyof T>[1] extends undefined ? T : never;

Here is the complete example in the TS playground.

Don't ask me about @jcalz solution, I don't want my head to explode. ^_^

doup
  • 841
  • 1
  • 9
  • 20