question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add typed return for Object.defineProperties

See original GitHub issue

Search Terms

Object.defineProperties typed

Suggestion

const newObject = Object.defineProperties(o, map);

Use Cases

Creating extensions of certain properties while still being able to type-check them

Examples

/** @type {NodeList} */
const nodeListObject = Object.defineProperties(/** @type {Node[]} */ ([]), {
    item: {
      enumerable: false,
      /** @param {number} [index] */
      value: function item(index) { return this[index]; },
    },
  });

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

The current type I’m using is the following:

interface ObjectConstructor {
  defineProperties<T1, T2 = PropertyDescriptorMap>(o: T1, properties: T2 & ThisType<T1>): T1 & {
        [K in keyof T2]: (
          T2[K]['get'] extends Function ? ReturnType<T2[K]['get']> :
          T2[K]['set'] extends Function ? Parameters<T2[K]['set']>[0] :
          T2[K]['value'] extends undefined ? any : T2[K]['value']
        )
      };
}

It seems alright but I would love to get some feedback. Currently, I’m targeting against .get() first, then .set(arg0) and finally .value.

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ExE-Bosscommented, Mar 10, 2021

Yours won’t correctly handle non‑writable properties, whereas mine is much more correct:


interface ObjectConstructor {
	defineProperty<
		T,
		P extends PropertyKey,
		V = P extends keyof T ? T[P] : unknown,
		W = P extends keyof T ? true : false
	>(
		target: T,
		property: P,
		descriptor: TypedPropertyDescriptor<V> & { readonly writable?: W },
	): (T &
		{ readonly [K in P as W extends false ? K : never]: V } &
		{ -readonly [K in P as W extends true ? K : never]: V })
		// Needs https://github.com/microsoft/TypeScript/issues/40562:
		// & (asserts target is T &
		//	{ readonly [K in P as W extends false ? K : never]: V } &
		//	{ -readonly [K in P as W extends true ? K : never]: V });

	defineProperties<
		T,
		M extends Record<string | symbol, PropertyDescriptor>
	>(
		target: T,
		properties: M & ThisType<T>,
	): ({} extends M ? T : T & {
			readonly [K in keyof M as M[K] extends { readonly writable: false } ? K : (K extends keyof T ? never : K)]:
				M[K] extends Readonly<TypedPropertyDescriptor<infer V>> ? V : any;
		} & {
			-readonly [K in keyof M as M[K] extends { readonly writable: true } ? K : (K extends keyof T ? K : never)]:
				M[K] extends Readonly<TypedPropertyDescriptor<infer V>> ? V : any;
		})
		// Needs https://github.com/microsoft/TypeScript/issues/40562:
		// & (asserts target is ({} extends M ? T : T & {
		//	readonly [K in keyof M as M[K] extends { readonly writable: false } ? K : (K extends keyof T ? never : K)]:
		//		M[K] extends Readonly<TypedPropertyDescriptor<infer V>> ? V : any;
		// } & {
		//	-readonly [K in keyof M as M[K] extends { readonly writable: true } ? K : (K extends keyof T ? K : never)]:
		//		M[K] extends Readonly<TypedPropertyDescriptor<infer V>> ? V : any;
		// }))
}
0reactions
edemainecommented, Jan 26, 2022

@ExE-Boss Your definition seems far more useful. Perhaps it would make sense to turn into a PR? Is #40562 essential?

Adding proper definitions of Object.defineProperties would be one way to approach getters/setters in CoffeeScript, which doesn’t currently have built-in support so recommends using defineProperty. Lack of TypeScript support came up in this discussion.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Object.defineProperties() - JavaScript - MDN Web Docs - Mozilla
The Object.defineProperties() static method defines new or modifies existing properties directly on an object, returning the object.
Read more >
Object defineProperties() in JavaScript - Scaler
defineProperties () is a method that creates, adds, and modifies the properties on an object and returns the object passed to it as...
Read more >
TypeScript: Assertion signatures and Object.defineProperty
return x * y; }. To comply with behavior like this, we can add an assertion signature that tells TypeScript that we know...
Read more >
Simulating Object.defineProperties in Typescript
defineProperties (someObject.prototype, { property: {get: function() { return value; } } ...
Read more >
JavaScript Object.defineProperties() Method - GeeksforGeeks
Props: This parameter is an object whose own enumerable properties constitute descriptors for the properties to be defined or modified. Return ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found