#`If` doesn't make a new type?

1 messages · Page 1 of 1 (latest)

versed frigateBOT
#
OnkelTem#4669

Preview:```ts
type Params = {
foo: string
}

declare function bar(params: Params): void

function test1(params: Partial<Params>) {
if (params.foo != null) {
bar(params)
}
}

function test2(params: Partial<Params>) {
const {foo} = params
if (foo != null)
...```

warped blade
#

What's going on here?

#

Why TS cannot check a property?

abstract iris
#

checking params.foo only ever narrows params if it is a discriminated union (with .foo as a discriminant)

#

that's not the case here (params is { foo?: string })

warped blade
#

oh, that..

#

so what is the way then to achieve it?

abstract iris
#

i think i'd have to see the real code to have an informed opinion, but if it's just one property and you don't care about the extra allocation then what you did in test2 seems reasonable

warped blade
#

It looks like this:


const params = {
  ...this.defaultCommand,
  ...(typeof input === 'string'
  ? {
    Text: input,
    TextType: isSsml(input) ? TextType.SSML : TextType.TEXT,
   }
   : input),
  };
}

if (params.OutputFormat == null) {
  throw new TtsError('OutputFormat is required');
}
if (params.VoiceId == null) {
  throw new TtsError('VoiceId is required');
}

const command = new SynthesizeSpeechCommand(params);

#

So yeah, test2 approach seems to be more simple in this case

abstract iris
#

an alternative approach would be to write your own type guard function

#

which takes a partial params and narrows it down to definitely include those properties

warped blade
#

So it turns into:

    const { OutputFormat, VoiceId } = params;

    if (OutputFormat == null) {
      throw new TtsError('OutputFormat is required');
    }
    if (VoiceId == null) {
      throw new TtsError('VoiceId is required');
    }

    try {
      const command = new SynthesizeSpeechCommand({...params, OutputFormat, VoiceId});
warped blade
abstract iris
#

yeah, you could return asserts params is Params

warped blade
#

That's perfect

#

function assertCommandProps(value: Partial<AmazonCommand>): asserts value is AmazonCommand {
  if (value.OutputFormat == null) {
    throw new TtsError('OutputFormat is required');
  }
  if (value.VoiceId == null) {
    throw new TtsError('VoiceId is required');
  }
}

// ...

assertCommandProps(params);
const command = new SynthesizeSpeechCommand(params);