The typescript compiler performs strict null checks, which means you can't pass a string | undefined variable into a method that expects a string.
To fix this you have to perform an explicit check for undefined before calling luminaireReplaceLuminaire().
In your example:
private selectedSerialForReplace(): string | undefined {
return this.selectedSerials.pop();
}
luminaireReplaceLuminaire(params: { "serial": string; "newserial": string; }, options?: any): FetchArgs {
............
}
const serial = this.selectedSerialForReplace();
if(serial !== undefined) {
luminaireReplaceLuminaire({serial, newserial: response.output});
}
Answer from Acevail on Stack OverflowThe typescript compiler performs strict null checks, which means you can't pass a string | undefined variable into a method that expects a string.
To fix this you have to perform an explicit check for undefined before calling luminaireReplaceLuminaire().
In your example:
private selectedSerialForReplace(): string | undefined {
return this.selectedSerials.pop();
}
luminaireReplaceLuminaire(params: { "serial": string; "newserial": string; }, options?: any): FetchArgs {
............
}
const serial = this.selectedSerialForReplace();
if(serial !== undefined) {
luminaireReplaceLuminaire({serial, newserial: response.output});
}
If you are sure that serial could not be undefined you can use the ! post-fix operator
luminaireReplaceLuminaire({serial: this.selectedSerialForReplace()!, newserial: response.output});
Converting nullable object values to strings in Typescript
TypeScript Type 'string | null' is not assignable to type 'string'
Maybe<string> vs string | null
I think it's mostly a matter of preference. Folks coming from Scala/Haskell invariable reach for an Option/Maybe, nearly everyone else uses the if/else.
Scala and Haskell have distinct syntax to make dealing with Maybe a little more concise, TypeScript doesn't at least in part because in most cases Maybe is redundant with strict null checks.
IMO, it's more idiomatic TypeScript to rely on type guards with strict null checks.
More on reddit.comtypescript - Convert variable from number to string only if not null, otherwise leave as null - Stack Overflow
What do people think of the ability to have multiple types like this? I found it super annoying when mapping between objects. If the same property names are used but one is string but the other property from the other class is string | null, the IDE complains. Are there any situations where you've found it helpful to be able to declare at type like this?
That's because the return type of Local storage is string | null, and not just string. To avoid this exception, you can first get the item from local storage and then use it like:
export async function GetCertainCoinByType(coinId: string) {
let tokenFromStorage = localStorage.getItem('token')
if (!tokenFromStorage ) {
throw new Error("no token supplied");
}
const response = await axios.get(URLofCertainCoins + `certain/${coinId}`,
{
headers : {
token : tokenFromStorage
}
});
return response;
}
First, check whether token is null, and if it is, exit the function.
Now response is a Promise anyway, since it's returned by an async function. You don't need to await Axios, then re-convert it to a Promise afterwards. You can directly return axios.get(...) and since this removes the only await, it turns out you don't even need the async/await syntax at all here.
export function GetCertainCoinByType(coinId: string): Promise<any> {
const token:string|null = localStorage.getItem('token');
if(!token){
console.log("No token!");
return ;
}
return axios.get(URLofCertainCoins + `certain/${coinId}`, {
headers : { token }
});
}
Hi there! Quick question to the functional buffs out there:
What's the advantage of using a Maybe<string> type over using string | null? With strict null checking you still need to handle the null case, but you avoid using external libraries and having to introduce new concepts to the other developers on the team.
Same for Either<Error, string> and string | Error.
I think it's mostly a matter of preference. Folks coming from Scala/Haskell invariable reach for an Option/Maybe, nearly everyone else uses the if/else.
Scala and Haskell have distinct syntax to make dealing with Maybe a little more concise, TypeScript doesn't at least in part because in most cases Maybe is redundant with strict null checks.
IMO, it's more idiomatic TypeScript to rely on type guards with strict null checks.
I would definitely prefer null. It's just more idiomatic TS. In Scala, the language is built around Option. In TS, it's built around null and undefined.
For example, look at optional chaining. That works with null, not Maybe.
Optional chaining might be helpful to conditionally cast the number to a string.
const result: string | null = (s ?? n?.toString()) ?? null;
It is still not so pretty, but it's a little more concise.
Optional chaining sources:
- MDN
- TypeScript
Arguably a bit easier to read at a glance:
const result: string | null = s || n?.toString() || null;
After reviewing my previous answer, it seems a complete overhaul of my previous answer is necessary. I was way over complicating it, as the short answer is that these are standards-specified special cases.
The specification for String() (String used as a function):
15.5.1.1 String ( [ value ] )
Returns a String value (not a String object) computed by ToString(value). If value is not supplied, the empty String "" is returned.
The ToString function (that exists internally, not in userland) is defined as follows (9.8):
"The abstract operation ToString converts its argument to a value of type String according to Table 13"
Argument Type | Result
Null | "null"
Undefined | "undefined"
This means that String(null) and String(undefined) go into this special table of types and just return the string values valued "null" and "undefined".
A user-land pseudo-implementation looks something like this:
function MyString(val) {
if (arguments.length === 0) {
return "";
} else if (typeof val === "undefined") {
return "undefined";
} else if (val === null) {
return "null";
} else if (typeof val === "boolean") {
return val ? "true" : "false";
} else if (typeof val === "number") {
// super complex rules
} else if (typeof val === "string") {
return val;
} else {
// return MyString(ToPrimitive(val, prefer string))
}
}
(Note that this example ignores the constructor case (new MyString()) and that it uses user-land concepts rather than engine-land.)
I got a bit carried away and found an example implementation (V8 to be specific):
string.js:
// Set the String function and constructor.
%SetCode($String, function(x) {
var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
if (%_IsConstructCall()) {
%_SetValueOf(this, value);
} else {
return value;
}
});
macros.py:
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg));
runtime.js:
function NonStringToString(x) {
if (IS_NUMBER(x)) return %_NumberToString(x);
if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
if (IS_UNDEFINED(x)) return 'undefined';
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
}
The NonStringToString (which is essentially what is of interest), is luckily defined in psuedo-JS-land. As you can see, there is indeed a special case for null/true/false/undefined.
There is probably just some extra checks and handling for special cases like null and undefined.
MDN says:
It's possible to use String as a "safer" toString alternative, as although it still normally calls the underlying toString, it also works for null and undefined.