3
const x = [{a: 1, b: 2}].map((d: any) => ({...d, c: 'something new'}))

how can I make x has c property on array of object above?

I tried

const x = ([{a: 1, b: 2}] as any).map((d: <{c: string}>) => ({...d, c: 'something new'})) but it doesn't seems it's the right syntax.

7
  • 1
    What's wrong with the output you get? The variable x will be an array who's zero-th item will have a, b, and c properties. Commented Apr 30, 2022 at 16:29
  • It doesn't work because your callback is wrong (d: any) =>. Never annotate the parameter type of an inline call back. Ever. Commented Apr 30, 2022 at 16:29
  • Write const x = [{a: 1, b: 2}].map(d => ({...d, c: 'something new'}). This uses type inference. You get more type information by writing fewer types Commented Apr 30, 2022 at 16:31
  • 1
    typescriptlang.org/play?#code/… works perfectly Commented Apr 30, 2022 at 16:39
  • 1
    by the time you're using as any you're not getting much value out of the type system. For an unknown you should still have a good idea of it's shape or at least it's general constraints. Commented Apr 30, 2022 at 16:43

2 Answers 2

2

You don't need the <> when specifying an inline type

const x = ([{a: 1, b: 2}] as any).map((d: {c: string}) => ({...d, c: 'something new'}))

You could type the result like this

const x: Array<{a:number; b: number; c:string;}> = [{a: 1, b: 2}].map((d) => ({...d, c: 'something new'}))

Or simply let TypeScript figure it out (preferred as @AluanHaddad mentioned)

const x = [{a: 1, b: 2}].map((d) => ({...d, c: 'something new'}));
Sign up to request clarification or add additional context in comments.

5 Comments

Why are you casting away the type of the array?
I am just pointing out the syntax error in the given code
Then it's not a complete answer because he also wanted to know how to have the property available on the resulting array elements. Also, while you used correct cast syntax, it's not in the same syntactic context as in OP.
this could be the right solution.
Much better now. Thanks for looking at feedback. The last approach should be preferred for myriad reasons
0

Sometimes it helps to name and annotate the types you want to figure out what's needed.

interface AB {
  a: number
  b: number
}

interface ABC extends AB {
  c: string
}

const x: ABC[]                      // annotate what's expected
  = [{a: 1, b: 2}]                  // input
  .map(
    ab =>                           // inferred type
    ({...ab, c: 'something new'})   // result is shape of ABC (per element)
  )

// Once more, allowing type inference to do the work
// just to show we can be succinct when we want to be
const y = [{ a: 1, b: 2 }].map(ab => ({...ab, c: 'something'}))
//    ^ NB: y is not typed as ABC[], but has the right shape

Personally I often like to specify the type on the receiving variable (const x: ABC[] ...) because this ensures that the result it the shape we expect (and if we hover over later, will show that type, not something that happens to be the right shape which might be hard to grok).

6 Comments

One problem here, is that you are not using a type annotation you were using a type assertion and they have different meanings. Type assertions make the code less type safe and should only be used when the compiler can't figure out what the types are. The way you're using them provides a false sense of security
Thanks, you're correct, its an assertion, you're implying its a type cast. The purpose is to show that {a:1, b:1} is of type AB ({a: 1, b: 'foo'} would produce an error).
Quite so but the problem is that [{a: 1}] as AB[] does not produce an error because it's a type assertion not a type annotation. You can't use type assertions to place a type annotation on an expression as they have subtle to drastically different meanings
Ah yes, I see your point. Thanks for the clarification.
That doesn't ensure exact types. It's standard subtype compatibility. You're just repeating the types.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.