TypeScript: Function adding property type error

🔎 Search Terms

Function addition attribute

🕗 Version & Regression Information

No solution is provided in typescript

⏯ Playground Link

No response

💻 Code

interface ReactiveEffectRunner<T = any> {
  (): T;
  effect: ReactiveEffect;
}
  const runner = _effect.run.bind(_effect) as ReactiveEffectRunner;

  runner.effect = _effect;

🙁 Actual behavior

const runner:ReactiveEffectRunner = _effect.run.bind(_effect);

When we use type annotations this way, we get an error: type “() => Missing attribute “effect” in any” but type “ReactiveEffectRunner< any>” This property is required in.

🙂 Expected behavior

How do we assign properties to a function if we don’t use as to make assertions?

I needed typescript to provide a solution for us to solve the problem of incorrect function assignment types, instead of using crude assertions to solve it. Because typescript can put forward solutions to solve problems, it will make the code more elegant. Looking forward to your reply, thank you! 🙏

### Tasks

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 18 (2 by maintainers)

Most upvoted comments

@Andy-gs

You can always use Object.assign to perform the assignment of expando properties to a function. But unfortunately, since https://github.com/microsoft/TypeScript/issues/40562 or https://github.com/microsoft/TypeScript/issues/42253 has not been implemented, Object.assign cannot be used as an assertion function to reflect the type change of the target.

Instead, you could write a custom function as a workaround.


function assign<T extends {}, U>(target: T, source: U): asserts target is T & U {
    Object.assign(target, source);
}

const runner = run
//Logic handling between run and effect
assign(runner, { effect });

runner;
// ^? const runner: (() => void) & { effect: () => void; }

  • There’s a different template for feature requests, this was filed as a bug report.
  • All relevant code should ideally be contained here in the issue and not only available at a link
  • You might be using some other UI to interact with this issue but I suggest you don’t keep adding new comments each time you have something to say if nobody has posted an intervening comment. You can edit existing comments as well.
  • If you blockquote something you should make sure that the response isn’t included in the quote or it’s hard for others to see where the quote ends and your response begins.

How do we assign properties to a function if we don’t use as to make assertions?

I’d suggest using Object.assign instead of assign properties directly. In this way the code you posted in https://github.com/microsoft/TypeScript/issues/55303#issuecomment-1669820606 could be written as:

-  const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
-  runner.effect = _effect
-  return runner
+  return Object.assign(_effect.run.bind(_effect), { effect: _effect })

But under certain conditions I have to assign the two separately

In that case the error message is correct: the type says that the property always exists, but there’s an observable period of time where it’s missing. That’s a real type violation, and it makes sense that you have to write a type assertion to acknowledge it.