-
(Somewhat related to #519.) Since the package exports the error types as: export * as errors from './util/errors.js' I can only really get a reference to an error as a value and not as a type. To use it as a type, I have to do something like: import * as jose from 'jose';
InstanceType<typeof jose.errors.JOSEError> // back to the type
// or...
import { errors } from 'jose';
const { JOSEError } = errors;
InstanceType<typeof JOSEError> // back to the type I might want a reference to the class as a type to write generic code like this: // Combines the static members of `JOSEError` with its constructor.
type JoseErrorClass<E extends InstanceType<typeof JOSEError>> = typeof JOSEError & {
new(...args: any[]): E,
}
function expectJoseError<E extends InstanceType<typeof JOSEError>>(error: Error | undefined, type: JoseErrorClass<E>): void {
expectNotNil(error);
expectInstanceOf(error, type);
// This `code` check is technically unnecessary because of the `instanceof` check above,
// but it does expand the scope of the example a bit.
expect(error.code).toBe(type.code);
} I could use that like this: expectJoseError(error, JWSSignatureVerificationFailed); All of this could be slightly simpler if the errors were exported in a way that allowed TypeScript to get them as types more easily. Maybe it's fine this way, though? Adding Those export function expectNotNil<T>(actual?: T): asserts actual is NonNullable<T> {
expect(actual).not.toBeUndefined();
expect(actual).not.toBeNull();
}
export function expectInstanceOf<T, A extends T>(actual: T, of: Newable<A>): asserts actual is A {
expect(actual).toBeInstanceOf(of);
} |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 2 replies
-
I admire your dedication to types ;) |
Beta Was this translation helpful? Give feedback.
-
Thanks, I think 😅. Actually getting to use TypeScript professionally in the last year or so has had its ups and downs. I get 🤩 when I see opportunities to write generic code, and having an expressive type system with generics just makes the star-eyes bigger, but it has arguably wasted a lot of time in many circumstances. I think TypeScript is probably a lot simpler when just consuming and not trying to produce broadly-reusable code. Anyway, I guess I never really asked a question. I suppose we could make a backwards-compatible change to the current export: Line 53 in 9bbe5fb By adding another export next to it. export * as errors from './util/errors.js'
export * from './util/errors.js' I think this would allow TS to import the errors as types, right? Because the import would look like: import { JOSEError } from 'jose' Though, if I were the maintainer, the idea of exporting the same module twice, differently, would probably bother me somewhat 😂. That said, I was much more distressed by the issue until I found out how to use An alternative would be that I could write a small addition to the docs (somewhere around here, I guess: https://github.com/panva/jose/blob/main/docs/modules/util_errors.md) that talks about the types vs. values thing and how to use @panva What do you think? |
Beta Was this translation helpful? Give feedback.
-
Go for it. |
Beta Was this translation helpful? Give feedback.
-
In v5.1.3 you can to get around the root export being an object with values as keys import { JOSEError } from 'jose/errors' |
Beta Was this translation helpful? Give feedback.
-
Ooh, nice! Yeah, I didn't want to do a deep import before because it would've been something like: import { JOSEError } from 'jose/dist/node/esm/util/errors.js' 😂 |
Beta Was this translation helpful? Give feedback.
-
Confirmed that this works! 🙌 |
Beta Was this translation helpful? Give feedback.
In v5.1.3 you can to get around the root export being an object with values as keys