-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow more constructs to work as type guards for unknown
#25720
Comments
Sure, why not! |
And one more thing: let foo: unknown;
if (typeof foo === "object") {
// foo should probably be narrowed to {[prop: string]: unknown} here
} |
At the least, at function f(u: unknown): object { return typeof u === "object" ? u : {}; } |
I was hoping interface SomeValue { a: string, b?: number, c: 'left' | 'right' }
function readValue(id: string): SomeValue {
const u: unknown = await someDataSource(id);
if (
typeof u !== 'object' ||
u === null ||
typeof u.a !== 'string' ||
b in u && typeof u.b !== 'number' ||
u.c !== 'left' && u.c !== 'right'
) {
throw new Error(util.format('Invalid value with id %O from some data source: %O', id, u));
}
return value; // TS is checking that the checks above actually verify the return type here
} This to me would be a better match to TS for what #26078 wants, but I wouldn't complain about adding quick-fixes to add the missing checks! (remember that |
I would like it if type guards with
I think the type promotion ought to work like so, if at all possible.
|
I realize I'm a bit late, but you might be interested in https://github.com/gcanti/io-ts -- provides a nice way to generate your necessary typeguards, though might be a bit heavy handed for the common usecase (and thus probably still worth considering this issue) |
Thanks for the suggestion, but that's probably not relevant to the discussion. |
I'd also like to add that |
Is there any update regarding this issue? I would love to use the unknown type, but at this point it's just too verbose to narrow it down to bigger objects. This proposal would make it a lot easier. |
Until this is fixed, this is a helper that can be used to make it easier to write manual type guards for
Example usage:
For more complicated use cases, using something like https://github.com/gcanti/io-ts is probably a better option than writing the type checks manually, but |
@butchler Similar to what you suggested (infect i started with that) function isAssumedType<T = Record<string, unknown>>(x: unknown): x is Partial<T> {
return x !== null && typeof x === "object";
}
// usage
if (isAssumedType<CommandCreator>(arg) && arg.execute && arg.host) {
return true;
} The main difference is that |
This is effectively the same as a type assertion (i.e. Type assertions are fine and have to be used sometimes, but personally I would avoid using something like |
typeof x.foo doesn't work -> Property 'foo' does not exist on type 'object'. |
That's an example of something I would like to work, but currently doesn't. |
Maybe something like this works.. It does the job for me.. Here 'result' is of type unknown. So narrowing down to the required type using user defined type guard seems to be the sane type-safe solution. Or are there are other possibilities as well? |
Would like to see this implemented.
Typescript still complains for the above code even though we check for all the cases before accessing the Using |
I would expect if (err?.message) {
// err is typed as { message: unknown, [k: string]: unknown }, or similar.
} |
The lack of better/easier type guards for catch (e: unknown) {
console.log(e?.message);
} I don't want to overcomplicate my code just because |
Crosslinking to #27706 |
Adding this kind of type of guards to Arrays, Maps and Sets could be done quite easily, Objects are be a bit more complicated. const inp = process.env.INPUT as unknown
const arr = ['a', 'b', 'c'] as const
if (arr.includes(inp)) {
console.log(inp)
// ^? "a" | "b" | "c"
}
const obj = {'a':1, 'b':2, 'c':3} as const
if (obj.hasOwnProperty(inp)) {
console.log(inp)
// ^? "a" | "b" | "c"
}
const map = new Map([['a',1], ['b', 2], ['c', 3]] as const)
if (map.has(inp)) {
console.log(inp)
// ^? "a" | "b" | "c"
}
const set = new Set(['a', 'b', 'c'] as const)
if (set.has(inp)) {
console.log(inp)
// ^? "a" | "b" | "c"
} |
Search Terms
unknown type guard
Related: #24439 (comment), #25172
Suggestion
Currently, only a very limited set of type guards are able to narrow the new
unknown
type:arg is any[]
) and probably some more in the lib filesHowever to make working with unknown types less awkward, I'd like to see a couple of other constructs being able to narrow the
unknown
type:Use Cases
Make
unknown
easier to work with!Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: