0

A simplified code example of what I'm talking about:

const err = returnTheError();

doTheThing(err);  // <-- I want this to fail compilation

function doTheThing(param: number[]) {
    // code  that assumes param is a `number[]`
    console.log("blah", param);
}

function returnTheError():any {
    return Error("uh-oh");
}

Assume I can't control the fact that returnTheError returns any - the caller will be dealing with an any type and there's nothing I can do about that.

I want a way to make sure nobody calls doTheThing with an any. If they have to do err as number[] or something, that's fine but at the moment it's just too easy in my code-base to accidentally pass an any on to methods that are relying on the compiler to make sure that the correct type of object is passed.

I have a TS playground showing the above example code, with all the "strict" options turned on, but still compiling.

Is there some change I can make to the definition of doTheThing that will cause the compiler to tell the caller they haven't checked whether err is actually the right type? Some way to say "parameter must be of type X and must not be an any"?

Shorn
  • 19,077
  • 15
  • 90
  • 168
  • No, this would violate the definition of `any`, which is that it can be used as any type. If you want the type-safety of not having any `any` types in your code, enable the `noImplicitAny` warning and don't write `: any` as an explicit type annotation anywhere in your code. – kaya3 Nov 14 '19 at 03:04
  • 3
    @kaya3 It's possible [like this](http://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAkgZgQQHYgDwBUA0UCa2ByAfFALxQAMUEAHsBEgCYDOUAFAIxQBkU6AlFAD8uKAC4o+ANwAoaXACuSAMbAAlgHskUBuvQALCPtVIA5hiq16zWIhQZsSCADcIAJwfyAtgCM3AbQBdQkJWMABDVzDPcX5xJ3VVBhkFZTVNbV0DI1NQiKjxJC9fV0CBAG9pKCqoAHoaqCV1BmgoYD0w4CgwpiYvCBZwyM8oVRYwqAADQp9-AInK6sakJnUAGwgAOlX1E1YAIm9VsL097EGovhkAX1kUlQ0tVwhgeVckfQgAUVdXdVdWPjiMIoKAVapQJ4vN5Qb6-f57eR6AC06hOl2kN2kSyYnTcrlIEOer3eBlhfwBMmkOg+2V2eMuVTqVB+fypmUMemMuz87GwACZsABmAIMpm9JRKCAQZhAA). Not necessarily *advisable*, but it can be done – jcalz Nov 14 '19 at 03:09
  • I guess if you absolutely cannot control `returnTheError`, then you can at least wrap it in a different function `returnWrapper() : Error | number[]` or whatever there makes sense as union type. Inside the wrapper function, just call `returnTheError` and check what the type is to cast appropriately and satisfy the return type. – VLAZ Nov 14 '19 at 03:09
  • @jcalz Thanks, I learned something: *"Even any isn’t assignable to never."* https://www.typescriptlang.org/docs/handbook/basic-types.html#never So of the two omnipotent types `any` and `never`, it's actually `never` that wins in a fight. – kaya3 Nov 14 '19 at 03:15
  • @jcalz - are there any significant downsides to this typing (other than the obvious hit to readability)? i.e. would it make the compilation process a lot slower if I used this throughout my app for error handling stuff? (pretty much every library out there types it's error handlers with `any`) – Shorn Nov 14 '19 at 05:07
  • 1
    I don't think the compile time should be a lot slower; I'd be worried more about unexpected interactions between it and other generic functions. Or generally I'd be worried about unexpected behavior, since the language really wants `any` to be more or less universally assignable both to and from other types. By preventing that you're choosing the road less traveled, and we don't really know the extent of what lies that way. – jcalz Nov 14 '19 at 13:45

0 Answers0