https://pulumi.com logo
#typescript
Title
# typescript
p

polite-napkin-90098

08/03/2023, 4:19 PM
I continually struggle with typing issues, probably as I learnt to code in a polymorphic language (perl) maybe someone who understands types can help: I want to set the number of tasks in a service to the number of subnets it is being deployed to, so that the Test stack, which is deployed to 1 subnet only runs one task, but Prod, which is more redundant, runs 2 or 3 depending on how many subnets I deploy to. But at the moment Test is deployed to 2 subnets, which I will fix soon, but in order to not incur additional costs whilst I shrink Test to 1 subnet I want to override that to be 1 in the case where we are in Test. So my code:
Copy code
let numTasks = vpc.publicSubnets.apply(subnets => subnets.length);

// that will work when we only have 1 subnet in the Test-vpc but for now

if (nom === 'test'){
  numTasks = 1;
}
This gives the error: stack/service.ts(14,3): error TS2322: Type '1' is not assignable to type 'Output<any>'. from the line where I try and force it to be 1 inside the if I've tried
Copy code
let numTasks: number = vpc.publicSubnets.apply(subnets => subnets.length);
making it a number in the declaration but that then errors with: stack/service.ts(9,5): error TS2322: Type 'Output<any>' is not assignable to type 'number'. I'm pretty sure my code is right and that on execution subnets.length will be a number, but the typing doesn't see what is obvious to me. Anyone got any pointers on how to fix this?
c

clever-sunset-76585

08/03/2023, 4:35 PM
Copy code
let numTasks = vpc.publicSubnets.apply(subnets => subnets.length);

// that will work when we only have 1 subnet in the Test-vpc but for now

if (nom === 'test'){
  numTasks = 1;
}
When you don't define an explicit type for
numTasks
, the compiler sees that its type is the result of the
apply()
which is
Output<T>
but then later when you try to re-assign that to a
number
, it's an error.
Copy code
let numTasks: number = vpc.publicSubnets.apply(subnets => subnets.length);
Here you are explicitly defining the type to be a
number
which is not correct because you are defining one type but then assigning a value of a different type,
Output<T>
. TypeScript supports union types, which allows you to do:
Copy code
let numTasks: number | Output<number> = vpc.publicSubnets.apply(subnets => subnets.length);
BUT you have another option. Pulumi has a built-in type called
Input<T>
which is a union of similar to the above. It's what all resource's properties are and it's why you can either give them plain values or promise-like values.
Copy code
let numTasks: Input<number> = vpc.publicSubnets.apply(subnets => subnets.length);
f

full-eve-52536

08/03/2023, 4:35 PM
In this case, it sounds like
numTasks
can either be of type `Output<any>`(Which is a Pulumi-specific type), or it can be of type
number
. I think what you want is:
Copy code
let numTasks: number | Output<number>
p

polite-napkin-90098

08/03/2023, 5:29 PM
ah yes, thanks both, I'd forgoten about union types. Also useful to know that Input<T> is a union type as you say. 😄
l

little-cartoon-10569

08/03/2023, 8:41 PM
In this case, you probably want it to be of type
pulumi.Input<number>
.
Alternatively, you could leave it as type
pulumi.Output<number>
and change the if-clause to
Copy code
if (nom === 'test'){
  numTasks = pulumi.output(1);
}
Mixing types like this, especially in a case like this where it seems that the if-clause is going to be short-lived and you'll remove it soon, is an opportunity for bugs to creep in. Try to simplify all your use cases.
f

full-eve-52536

08/03/2023, 8:42 PM
It's possible to use
pulumi.Output()
as a function? Hmm..didn't know that. TIL
l

little-cartoon-10569

08/03/2023, 8:43 PM
No.
pulumi.Output
is a type.
pulumi.output()
is a function.
It wraps its parameter in a
pulumi.Output
.