#`any` type is not allowed?

15 messages · Page 1 of 1 (latest)

crimson spade
#

Ever?

I created this Result type that I use for the return type of several different functions throughout my code.

type Result = {
    success: boolean
    error?: Error
    product?: any
}

The purposes of the functions vary. Some of them produce an object of one type or another. Some of them produce a string. Several of them use try...catch to execute a database (SQLite) query. Thanks to this type, I can handle the return value the same way for all of them. Given the variety of products, I thought that this was a really appropriate use for any.

I was actually pretty proud of myself. This is my first TypeScript project. I think I'm using it properly. Is there a different way that I should be doing this?

I realize that this is just a warning and I can probably ignore it.

I guess this is a linter thing that I can configure away if I find the right option, but I think people smarter than me set this as a sensible default so it means that I'm probably doing it wrong.

I am using Deno for this project, but I'm not sure that's relevant here since this is specifically a TypeScript thing.

silver sage
#

Aside from the warning, this sounds like a place where you might want to use generics

#

You could also use a union to differentiate types a bit better

#
type SuccessResult<T> = {
  success: true
  data: T
}

type FailureResult = {
  error: Error
}

type Result<T> = SuccessResult<T> | FailureResult;
#

Ignoring the above, typically instead of any it's recommended to use unknown assuming the type is truly unknown to you. Here's a good post that explains it

crimson spade
#

Thank you!
That's really excellent information. Both Generics and the unknown type provide better ways of doing what I'm trying to do.

I'm leaning toward using unknown mostly because I'm already doing a lot of the type checking that's required to use it effectively. I have a lot of if (result.success) and if (result instanceof Error) already. Along with the tagged union types, also explained in the article and a linked related article, it's perfect for my needs.

silver sage
#

Using unknown is generally considered to be in the same category as any, ie. bad. You only need it when you absolutely have to

cedar adder
#

i disagree that it's in the same category. unknown is safe/sound, it's just the top type. any turns off type-checking entirely and is very much not safe/sound

#

i would agree that when you find yourself using unknown (especially in a concrete type like this vs a constraint) there's often a way to be more precise and that's usually a good idea. like i'd definitely make the type generic instead in this case

crimson spade
#

I ended up using the tagged union types referenced in the article by Marius Schulz (a.k.a.: Discriminated Unions), but not unknown.

Right now I'm using object. I wrapped some of my return values in curly braces, but I'm planning to further refine that object by creating an interface to represent one of the more complex return values and unioning that with number for the other possible return values.

Current Version:

type Result =
    | { success: true; product?: object }
    | { success: false; error: Error }
#

I'm also in the process of figuring out how to do something better with those Errors. I think I should be throwing them rather than returning them and using try... catch... finally to make it act right.

white turret
#

sounds like you need to use generics, so that you can pass the exact type when needed

#
type Result<T> =
    | { success: true, product: T }
    | { success: false, error: Error };
silver sage