Is this type of unmarshalling allowed? ```config: ...
# typescript
s
Is this type of unmarshalling allowed?
Copy code
config:
  aws:region: us-east-1
  pulumi_node:application-dashboards:
  - namespace: api-platform
    topic:
    - ap-topic-1
    - ap-topic-2  
    applications:
    - name: template-api-reference
      topic:
      - tar-topic-1
      - tar-topic-2
    - name: msk-healthcheck-consumer
    - name: msk-healthcheck-producer
Copy code
let pulumiConfig = new pulumi.Config()
let applicationDashboards = pulumiConfig.getObject<ApplicationDashboards[]>("application-dashboards")

export interface ApplicationDashboards {
    namespace: string
    topic: string[]
    applications: {
        name: string
        topic: string[]
    }[]
}
This produces the output below
Copy code
console.log(JSON.stringify(applicationDashboards))
console.log(applicationDashboards)
Copy code
[{"applications":[{"name":"template-api-reference","topic":["tar-topic-1","tar-topic-2"]},{"name":"msk-healthcheck-consumer"},{"name":"msk-healthcheck-producer"}],"namespace":"api-platform","topic":["ap-topic-1","ap-topic-2"]}]
    [
      {
        applications: [ [Object], [Object], [Object] ],
        namespace: 'api-platform',
        topic: [ 'ap-topic-1', 'ap-topic-2' ]
      }
    ]
l
Did it produce the output you showed? So it's working?
s
why is the application an Object?
l
Because it's not a string, number or boolean.
"Object" is the string representation of any Object.
s
this does not make sense to me
Copy code
config:
  aws:region: us-east-1
  pulumi_node:application-dashboards:  - namespace: api-platform
    topic:
    - ap-topic-1
    - ap-topic-2
    applications:
    - template-api-reference
    - msk-healthcheck-consumer
    - msk-healthcheck-producer
this umarshals like this using the same interface as before
[ { applications: [ 'template-api-reference', 'msk-healthcheck-consumer', 'msk-healthcheck-producer' ], namespace: 'api-platform', topic: [ 'ap-topic-1', 'ap-topic-2' ] } ]
the problem comes from wanting to iterate over the applications accessing it requires a check for undefined
what is the best way to check for that?
l
I'm afraid I don't understand the question.
applications
is supposed to be an array of objects, duck-typed as
{name:string; topics:string[]}
. The unmarshalled object above shows
applications
as an array of strings. Are you asking why it's getting an array of strings instead of the expected objects?
s
I have a function that looks like this
Copy code
function findTopic(dashboards: ApplicationDashboards[], splitStr: string[]): string[] {
    const namespace_name = splitStr[0]
    const application_name = splitStr[1]
    // console.log(namespace_name + " " + application_name)
    let appTopics: string[] = []
    for (var ns of dashboards) {
        if (ns.namespace === namespace_name) {
            if (ns.topic.length === 0) {
                return []
            }
            appTopics = appTopics.concat(ns.topic)
            for (var app of ns.applications) {
                console.log(app)
                if (app.name == application_name) {
                    appTopics = (app.topic?.length > 0) ? appTopics.concat(app.topic) : appTopics
                }
            }
        }
    }
    return appTopics
}
With the way that this is unmarshalled i.e. with an array of objects this loop
for (var app of ns.applications)
is undefined
if I have a test like this
Copy code
@test 'typescript interface' () {
    interface SquareConfig {
      color?: string
      width?: number
      thing?: {
        name?: string
      }[]
    }
    // interface something {
    //   name?: string
    // }
    let newSquare = { color: "white", area: 100, thing:[{name:"Janitha"},{name:"Jayaweera"}] }
    testassert.deepStrictEqual(newSquare.area,100)
    testassert.deepStrictEqual(newSquare.thing[0].name,"Janitha")
    testassert.deepStrictEqual(newSquare.thing[1].name,"Jayaweera")

  }
given a unit test like this it behaves as I expect it. I can index and access. i.e. what I want to do with the for loop above
l
I'm still very unclear on what is not working the way you expect. Perhaps this is it? Your first question has this YAML:
Copy code
applications:
    - name: template-api-reference
      topic:
      - tar-topic-1
      - tar-topic-2
    - name: msk-healthcheck-consumer
    - name: msk-healthcheck-producer
And this corresponding interface definition:
Copy code
applications: {
        name: string
        topic: string[]
    }[]
In the example YAML, topic is optional, but in the interface, it is not. Would making this change help?
Copy code
applications: {
        name: string
        topic?: string[]
    }[]
s
Agreed it - topic - is optional how should this statement be written?
console.log(applicationDashboards[0].applications)
Copy code
error: Running program '/workspaces/pulumi_node' failed with an unhandled exception:
    TSError: ⨯ Unable to compile TypeScript:
    index.ts(21,13): error TS2532: Object is possibly 'undefined'.
    
        at createTSError (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:261:12)
        at getOutput (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:367:40)
        at Object.compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:558:11)
        at Module.m._compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:439:43)
        at Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
        at Object.require.extensions.<computed> [as .ts] (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:442:12)
        at Module.load (node:internal/modules/cjs/loader:989:32)
        at Function.Module._load (node:internal/modules/cjs/loader:829:14)
        at Module.require (node:internal/modules/cjs/loader:1013:19)
        at require (node:internal/modules/cjs/helpers:93:18)
l
console.log(applicationDashboards?[0].applications)
s
same error
console.log(applicationDashboards[0]?.applications)
Copy code
error: Running program '/workspaces/pulumi_node' failed with an unhandled exception:
    TSError: ⨯ Unable to compile TypeScript:
    index.ts(21,13): error TS2532: Object is possibly 'undefined'.
    
        at createTSError (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:261:12)
        at getOutput (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:367:40)
        at Object.compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:558:11)
        at Module.m._compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:439:43)
        at Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
        at Object.require.extensions.<computed> [as .ts] (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:442:12)
        at Module.load (node:internal/modules/cjs/loader:989:32)
        at Function.Module._load (node:internal/modules/cjs/loader:829:14)
        at Module.require (node:internal/modules/cjs/loader:1013:19)
        at require (node:internal/modules/cjs/helpers:93:18)
missplaced null check
else this is the error
Copy code
error: Running program '/workspaces/pulumi_node' failed with an unhandled exception:
    TSError: ⨯ Unable to compile TypeScript:
    index.ts(21,51): error TS1005: ':' expected.
    index.ts(21,39): error TS2339: Property 'applications' does not exist on type 'number[]'.
    
        at createTSError (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:261:12)
        at getOutput (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:367:40)
        at Object.compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:558:11)
        at Module.m._compile (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:439:43)
        at Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
        at Object.require.extensions.<computed> [as .ts] (/workspaces/pulumi_node/node_modules/@pulumi/pulumi/node_modules/ts-node/src/index.ts:442:12)
        at Module.load (node:internal/modules/cjs/loader:989:32)
        at Function.Module._load (node:internal/modules/cjs/loader:829:14)
        at Module.require (node:internal/modules/cjs/loader:1013:19)
        at require (node:internal/modules/cjs/helpers:93:18)
https://pulumi-community.slack.com/archives/CJ909TL6P/p1626917721204500?thread_ts=1626916816.202100&amp;cid=CJ909TL6P yes this is one problem, why is it unmarshalling without respecting the interface - should have errored out, trying to nest seems to break
l
I'll find the library that's doing the YAML unmarshalling, their docs might explain it better.
I can't figure it out. No golang experience here at all. Pretty sure it's this library though: https://pkg.go.dev/gopkg.in/yaml.v2#Unmarshal
s
that package is not the problem https://play.golang.org/p/AMj6YhZLsz6 It's getObject in these lines. How did you know to go find the the yaml package above?
Copy code
let pulumiConfig = new pulumi.Config()
let applicationDashboards = pulumiConfig.getObject<ApplicationDashboards[]>("application-dashboards")
l
Experience 🙂 I investigated a different issue in unmarshalling a few months ago and found the problem was in the golang lib. Worked around it in Typescript.