0

I'm still learning various coding styles with regard to Typescript and Angular.

Today I came across this with no comments to the method that was coded.

It appears to me that it is somehow enforcing that the value passed in must be one of the defined values but does not make use of ENUM to enforce it which leads to other issues in a large codebase with no documentation.

Am I correct that this is enforcing the value must be equal to one of the || options?

static getEndpoint = (type: string = 'alpha' || 'bravo' || 'charlie) => {}

To me I would have done something along the lines of and ENUM and

export enum MyTypes {
  ALPHA = 'alpha',
  BRAVO = 'bravo',
  CHARLIE = 'charlie',
}

and then

static getEndpoint = (type: MyTypes = MyTypes.ALPHA) => {}
edjm
  • 4,830
  • 7
  • 36
  • 65
  • 1
    You are correct :) – Brandon Miller Sep 16 '21 at 11:43
  • @BrandonMiller Thank you for clarifying. I was unable to find any documentation with Google explaining what I was seeing. – edjm Sep 16 '21 at 11:46
  • 2
    "*Am I correct that this is enforcing the value must be equal to one of the || options?*" no, the *default value* is equal to `'alpha' || 'bravo' || 'charlie'` and *that* expression only ever resolves to `'alpha'` [Logical operators in JavaScript — how do you use them?](https://stackoverflow.com/q/4535647) | [Logical operator || in javascript, 0 stands for Boolean false?](https://stackoverflow.com/q/9579262) | [JavaScript OR (||) variable assignment explanation](https://stackoverflow.com/q/2100758) – VLAZ Sep 16 '21 at 11:47
  • @VLAZ So is this code that uses that format just incorrect? Why would anyone right it like that? – edjm Sep 16 '21 at 11:49
  • @Elijah Seems like a mistake. Either unintentional for some reason or the author just doesn't know what they wrote. – VLAZ Sep 16 '21 at 11:50
  • oops, my mistake. @VLAZ is correct. You would normally use a single "|" to achieve a lazy enum. As far as || on instantiation, you've got me there. Never seen that lol – Brandon Miller Sep 16 '21 at 11:53
  • @VLAZ Thank you for the links. Much appreciated. – edjm Sep 16 '21 at 11:55

2 Answers2

3

If it were:

static getEndpoint = (type: 'alpha' | 'bravo' | 'charlie' = 'alpha') => {}

then yes. But currently it will accept every string and default to 'alpha'. Because:

(type: string = 'alpha' || 'bravo' || 'charlie')
//     ^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//       |                  \ the default value, 
//       |                    which reduces to: 'alpha'
//       |
//       \-- the actual type (here: string)

Ref: Literal Types

Yoshi
  • 54,081
  • 14
  • 89
  • 103
2

The code shown won't compile, it's missing a '. But assuming you really have this:

static getEndpoint = (type: string = 'alpha' || 'bravo' || 'charlie') => {}

then no, the code isn't enforcing anything except that type must be a string. The code above is functionally equivalent to:

static getEndpoint = (type: string = 'alpha') => {}

The part after the = is a default parameter value, and the expression 'alpha' || 'bravo' || 'charlie' evaluates to 'alpha'.

It was probably meant to be this:

static getEndpoint = (type: 'alpha' | 'bravo' | 'charlie') => {}

That's a union of string literal types. That would require that the type of what was passed for type is the string literal type "alpha", "bravo", or "charlie". This works:

getEndpoint("alpha");

but this doesn't, even if s contains the string "alpha", if that can't be proven at compile-time:

let s: string;
// ...something setting `s`...
getEndpoint(s);

In that form, the union of string literal types performs a similar function to an enum.

To me I would have done something along the lines of...

You've made two changes there:

  • Using an enum
  • Providing a different default value — well, no, it's the same default, but you've done it on purpose :-)

Your version is just fine, but if you wanted to do that with string literal types, it would look like this:

static getEndpoint = (type: 'alpha' | 'bravo' | 'charlie' = 'alpha') => {}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Greatly appreciate the details. Yes I made a typo by fogetting the ' in the OP. Based on what you have provided and the other material and links the others have posted, it looks to me as though the originator of the code did this incorrectly. There should NOT be a default value and the call must be specific with passing in a value. I would opt for the use of an ENUM as that is more intuitive IMO and managing custom application values are easier when they are all in files with naming patterns that you know what's in them rather than hunting down rogue methods with values hard coded in them. – edjm Sep 16 '21 at 12:12
  • @Elijah - Quite. :-) Although for the centralization part, you can also do `type EndPointType = "alpha" | "bravo" | "charlie";`. But it's still easier with IDEs (I think) to find all references to an enum than to a string literal type. :-) Happy coding! – T.J. Crowder Sep 16 '21 at 12:14