Repository navigation
Some way to express a non-null / non-undefined any would be nice #7648
Description
Activity
Seems conceptually similar to 'outersection' types, where you'd express it something like
any - null - undefined, where you start with a type and 'subtract' other types from it.That issue is closed as too complex but there's a comment about it from a recent backlog slog that says: "Revisit in context of type operators"
Arnavion commented
on Mar 23, 2016 ContributorAuthorMore actionsYes, I remember, which is why I'm asking for a much easier form.
This issue is probably going to come up more often when code starts using
--strictNullChecks. In that mode types likestringandnumberwill excludenullandundefined, but what aboutany? Does that still includenullandundefinedunder strict null checks?In a way, it would seem consistent under
--strictNullChecksthatanyexcludesnullandundefined, and you would have to be explicit to include them, i.e.any | null | undefined. OTOH that seems like a logical contradiction of the special semantics ofany.Arnavion commented
on Mar 23, 2016 ContributorAuthorMore actionsYes,
--strictNullChecksis the context of this issue, and yes since nullability is via union types,anyis allowed to benullandundefined. Hence this issue.Maybe a new builtin type name like
someorsomething, wheresome | null | undefined ≡ anyReacted by Ketut Sandiarsa, Kerem Kat, Jan Aagaard, Antonio García, Toni Ruottu, ipcjs, Peng Li, Donald Oakes, Seva Golovanov, strblr and 18 moreThis type already exists. It's
{}declare function f(x: {}): void; f(0); // ok f(""); // ok f(true); // ok f({}); // ok f(null); // error f(undefined); // error
Reacted by Ludwig Stecher, Haroldo de Oliveira Pinheiro, Daniel Neveux, Pavlo Michal, Daniele Orlando, Edsolater, Simon Weaver, Nahuel Palumbo, André Kovac, Tadatoshi Tokutake and 10 moreReacted by Nico Greenarry, Anthony, vincenteof, Alauddin Afif Cassandra, btoo, Dainius Daukševičius, Toni Ruottu, Dmitri Pavlutin, ipcjs, Dmitrii and 21 moreReacted by david, Ketut Sandiarsa, Antonio García, Ludwig Stecher, Giuseppe Mandato, 流浪大法师, 7nik and TwistedMindaReacted by Ricardo Fernández SerrataI don't think
{}is the same thing at all. Using{}as the return type in the OP's examples have a very different meaning thanany - null - undefinedor however it could be expressed.Arnavion commented
on Mar 23, 2016 ContributorAuthorMore actionsBeat me to it :) For reference, see #5451 (comment)
Edit: Although atleast for the first case, a generic
T extends {}with return typeTshould work?RyanCavanaugh commented
on Mar 23, 2016 MemberMore actions{}would be the equivalent type from the input side.On the output side, it would be
string | number | boolean | object(note thatobjectis unimplemented, see #1809)Reacted by Gerardo LimaArnavion commented
on Mar 23, 2016 ContributorAuthorMore actionsThanks. It's a bit wordy, but I suppose the set of primitive types is well-known.
Is there any reason to use
{}over that for the input side?RyanCavanaugh commented
on Mar 23, 2016 MemberMore actionsFor callback parameter type annotations, one may be preferable over the other depending on the scenario.
If function return types in
.d.tsfiles are changed fromanytostring | number | boolean | object(for the purposes of excludingnullorundefinedas in the OP's examples), wouldn't that break a lot of user code? Type assertions would have to be added where they were previously unnecessary onanytypes. Not saying that's good or bad, just a big breaking change.RyanCavanaugh commented
on Mar 23, 2016 MemberMore actionsFor return types, it's probably best to leave it as
any. I'm not sure what use there is in saying "any but not null or undefined" since you're able to assign it to a non-null type anyway.Arnavion commented
on Mar 23, 2016 ContributorAuthorMore actionsIt would be self-documenting that it won't return a null. It may be useful for user functions as well that can return any object but never null, like a
parse(input, rule): outputfunction.This would be only for documentation purposes as TS allows dereferencing
anyor assigning to non-null variables.Ideas:
- Should we rather annotate methods that may return null as
any | null? This would be consistent with other types and OK for doc. - Is
!going to fly for types as well? It could be useful with generics like:function nonNulls<T>(array: T[]): T![]. If it does then maybe we should simply acceptany!.
- Should we rather annotate methods that may return null as
31 remaining items
I have this related question - https://stackoverflow.com/questions/51236491/typescript-type-representing-everything-but-undefined
if someone wants SO points please take a look thx
I was thinking something like this would be nifty:
export type NotUndefined = !undefined
probably a dumb idea, but at least you get the picture
We just want a built-in thing type that's exactly like any except it doesn't allow null / undefined.
object | string | boolean | symbol | number?type yourType = object | string | boolean | symbol | number; function f():()=>yourType{ return (window as any).returnAnyObj(); } var res=f() res.xxx=1 // error!we just need any object, when use MemberExpression won't throw error
In case someone need examples, here is a question I had posted some time ago.
https://stackoverflow.com/questions/53612681/typescript-function-cannot-return-undefinedAlgebraic data type operators exist in TS.
Exclude<T>,NonNullable<T>seemed nice, until I tried them withany, and they do work withany.declare function f(x : NonNullable<any>) declare const a : string | null f(a) //works```
And by the way,
object | string | boolean | numberis bad form. Not to mention it'sobject | string | boolean | number | symbol | bigintas of comment. Each time a new primitive is added you need to update it.interface State { message?: some; }
Misha Kaletsky (@mmkal) Seems to be related to #13195
Reacted by 流浪大法师 and Misha Kaletskytype Nil = null | undefined;
type NotNil = Nil extends T ? never : T extends Nil ? never : T;Try it out, it does not work. You'll find the appalling fact that
NotNil<any>is now an alias ofnever. This is because any extends anything.I know it's not the same thing, you won't be able to use any but you're guaranteed you need to specify a type which could not be null
I appreciate that, however the title of this issue is explicitly non-nullable any.
anydoesn't mean that the value can be of any type. It means "please disable all type checking thanks". It doesn't make a whole lot of sense to "disable type checking except for null checks".To declare a variable that can be of any type you can use
unknown. Sadly, you can't doNonNullable<unknown>because it's not a union type, sostring | number | boolean | symbol | bigint | objectseems to be the only way to do this right now.Reacted by TMTron, Sal Rahman and Dennis FredeReacted by Mathias Schreck, Lennart Hildebrandt, Jihyeon Kim (김지현), 流浪大法师, Sal Rahman and Carlos AlexandreI'm ok with doing
string | number | boolean | ...as a workaround but is there some way to display a custom alias likeDefinedorSomein error messages instead of the full definition?I'm working with generated code which contains lots of statements about things that are defined and the error messagages are extremely hard to read because of such long definitions. See https://github.com/maasglobal/maas-schemas-ts/blob/master/src/core/booking.ts for example.
Reacted by Michal Burger, Lennart Hildebrandt, David Wickes and 流浪大法师With optional chaining, I think there is another use case?
const a: any = null; const chained: string|null = a?.foo; // This should error const nullable: Exclude<any, undefined> = a?.foo; // This should error const neverNull: Exclude<any, null> = a?.foo;Because an optional chained
anyis stillany, a subsequent check on the assignednullableparameter can make incorrect assumptions:if (chained !== null || nullable !== null) { console.log(chained.length); // throws because chained is undefined console.log(nullable.length); // throws because nullable is undefined }Where as if there was a non-null
any, comparing the optional chained result to null can be caught at compile time:if (neverNull !== null) { // always true }- locked as resolved and limited conversation to collaborators
on Apr 6, 2023

While updating the various .d.ts to have
| nulland| undefined, I came across some typings that useanybut don't allownullorundefined.Object.defineProperty:
oand the returned value cannot benullorundefined.Object.setPrototypeOf:
oand the returned value cannot benullorundefined.protocan benullbut notundefined.etc.
I think there is value in being able to express both "This can be any type including null and undefined" and "This can be any type excluding null / undefined", but there is no way to express the latter.