0

I have a function that crashes if the parameter sent is the instance of any class or is a Function.

So I need to write a Type that shows a compile-time error if we try to pass an instance of a class to that function. I tried the following but it can disallow only Function

// type Disallowed = instanceof any
type Disallowed =  Function 
type Input<T> = T & (T extends Disallowed ? never : T);


// Accepts anything number, string, bool, json object, ... except instance of class and functions
function saveData<T>(data: Input<T> ) { ... }
class A {}
let foo = new A{}
saveData(foo) // should produce compile error
saveData(()=>{}) // already dissallowed
TSR
  • 17,242
  • 27
  • 93
  • 197
  • 2
    All object literals are instances of `Object`... `({}) instanceof Object === true`. And [JSON](https://en.wikipedia.org/wiki/JSON) is a `string`. So you want a union of all non-object and non-function types? – jsejcksn Jan 09 '23 at 03:59
  • FYI [There's no such thing as a "JSON Object"](https://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/) – Phil Jan 09 '23 at 03:59
  • Don't think so. What is the usecase? Functions are understandable but why do you want to disallow class instances? [Class instances are also serializable using `JSON.stringify`](https://stackoverflow.com/a/40201783/8822610) – vighnesh153 Jan 09 '23 at 04:13
  • Maybe [this approach](https://tsplay.dev/WG499w) meets your needs? The compiler does distinguish between `interface`/`class` instance types and object literal types, but it's sketchy, since those types are generally mutually assignable (you can always assign a class instance to a structurally identical object literal type and then pass that value into your function, as shown). Should I write this up as an answer or am I missing something? – jcalz Jan 09 '23 at 04:20
  • 1
    Hard to imagine why a class instance would crash a function, but not an object. Could you elaborate? Seems like the function crashing in that case is the problem to be fixed, rather than preventing that case from happening, but I could be wrong. I guess you should specify whether "JSON object" means string or Object as well. – Chris Hamilton Jan 09 '23 at 04:26
  • This is firestore sdk doing this nasty thing. It would crash if you pass any instance of a class. Written by google, not me – TSR Jan 09 '23 at 04:31
  • @jcalz thanks for your suggestion, but I also found that but it does not work because interface should be allowed. I even asked this question https://stackoverflow.com/questions/75052531/argument-of-type-foobar-is-not-assignable-to-parameter-of-type-jsonobject-i?noredirect=1#comment132444433_75052531 before posting but no one found an answer – TSR Jan 09 '23 at 04:40
  • Then there's no way to do this. Class instances *are* interface types in TS (if you have a class named `Foo` then there is an interface named `Foo` corresponding to its instances). You might have to make do with a runtime check, but first you'd need to describe what precisely is causing the crash; all objects are instances of some "class", even object literals., so presumably it's something other than just what the constructor function is. So either there's isn't enough information to answer, or the answer is "sorry, that's impossible". How would you like to proceed? – jcalz Jan 09 '23 at 15:09
  • It's ok if it is not possible. This is caused by Firestore sdk, if you pass an instance of a class, it will produce an error. Just curious though if this will be implemented one in TS, if not, is there any technical feasible limiting this. I am assuming this shouldn't be too hard since Typescript already knows it's an instance of class `A` – TSR Jan 09 '23 at 15:31
  • After reviewing [your linked question](https://stackoverflow.com/q/75052531/438273), it seems clear to me that this question is just a rewording of the other one: it appears to be about accepting any value that can be losslessly serialized as a JSON string. e.g. https://tsplay.dev/mZQDoN – jsejcksn Jan 09 '23 at 15:55

0 Answers0