-
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
Suggestion: The object
primitive type
#1809
Comments
object
primitive typeobject
primitive type
It'd be useful to list some APIs other than the |
In the javascript core api except from Edit: underscore collection work with any types |
Discussed at suggestion review meeting. This all makes sense, but we need to justify the complexity of a new primitive type with the number of errors / richness of description it is able to provide. Basically, more examples of APIs that can't operate on primitives, especially ones that aren't "expert" APIs (e.g. Proxies) |
Posting more as reference than recommendation 😉 interface String { _primitiveBrand?: string; }
interface Boolean { _primitiveBrand?: boolean; }
interface Number { _primitiveBrand?: number; }
interface ObjectOnly { _primitiveBrand?: void; }
function fn(x: ObjectOnly) { }
// Error
fn(43);
// Error
fn('foo');
// OK
fn({});
// OK
fn(window); |
+1 on this proposal. I wouldn't consider This proposal will also solve the problem of typing "object bags" where each property is optional, but other primitive types should be disallowed. |
|
I think the title is a bit confusing since it mentions the word "primitive". This could alternatively be called the "ECMAScript object type" or the "Runtime object type". Which would be assignable from anything other than primitive types (including let isObject (x) => typeof x === "object"; According to MDN, this is the output of Undefined: "undefined" Without this type, there is no way to correctly match a precise type for the above mentioned guard, not even as a user-defined guard. This is also essential for use with any function that strictly requires an object that has properties and allows Having functions and constructors excluded, though, would be a bit limiting in some cases, so there could be another type that would include them as well and called the "non-primitive object type". A partial workaround could be the union |
Accepting PRs. This seems to be a common problem; this will be a breaking change for anyone brave enough to have written Side note: We're all wondering where @fdecampredon has been! |
@RyanCavanaugh Change of town of work, and unfortunately not a lot of typescript in my new job :D |
Great. I want to use this type in TS1.8. |
I would also like to see something like an
I'll take these in order. APIsAPIs such as function theAnswer() {}
let map = new WeakMap();
map.set(theAnswer, 42);
console.log(map.get(theAnswer)); // 42 This is as true for custom APIs as it is for built-in APIs. If I expect an object, I usually just want a bundle of properties. Functions are just callable bundles of properties. InheritanceSince class DeepThought {
static getAnswer() {
return 42;
}
}
let computer = Object.create(DeepThought);
console.log(computer.getAnswer()); // 42
console.log(Object.getPrototypeOf(computer)); // [Function: DeepThought] While the example above is a bit silly, it just illustrates that APIs that use the So I would suggest that the function isObject(value) {
return typeof value === 'object' || typeof value === 'function';
} Use CaseI have a project called Deep Map that recurses through the key-value pairs of nested objects and transforms primitive values along the way. As such, it distinguishes between primitive and non-primitive types. I had to define a custom interface NonPrimitive {
[key: string]: any;
[index: number]: any;
}
export class DeepMap {
// ...
private mapObject(obj: NonPrimitive): NonPrimitive { /* ... */ }
} This is not the first time I've had to define the export class DeepMap {
// ...
private mapObject(obj: object): object { /* ... */ }
} As I suggested above, I don't really care whether the |
I would agree that functions are |
Ok, I thought that must have been the intent. I just thought maybe I was missing something with all this talk of |
would this const foo: object = {};
foo.bar = 'baz'; |
No |
Fix #1809, introduce non primitive object type
What's the practical difference between export class DeepMap {
// ...
private mapObject(obj: object): object { /* ... */ }
} and export class DeepMap {
// ...
private mapObject(obj: Object): Object { /* ... */ }
} ? (Using |
@trusktr All values other than |
The
object
primitive typeThis proposal describe a new primitive type for typescript
object
.Use case
JavaScript core api contains some functions that takes
object
as parameter :Object.getPrototypeOf
Object.getOwnPropertyDescriptor
Object.create
Currently there is no way in typescript to prevent passing other primitive type (
string
,number
, etc ...) to those functions.For example
Object.create('string')
is a perfectly valid typescript statement, even if it will ends up with an error.Creating a new
object
primitive type would allows to model more correctly the signature of those function, and every function that share similar constraint.Type Checking
Assignability
The
object
type is the equivalent of{}
minus the assignability of other basic type, that means that :object
object
{}
andany
This behavior is coherant to how javascript works, the type represent every value that respect the constraint
typeof value === 'object'
plusundefined
.Type guard
A new type guard has to be introduced for
object
:typeof value === 'object'
.Optionally the compiler could also accept comparaison with the
Object
function cast :Object(value) === value
.The text was updated successfully, but these errors were encountered: