The accepted answer is actually not answering the question since it was asked for a generic way.
Here is one that is similar and will also cast the return type properly:
type RecursivelyReplaceNullWithUndefined<T> = T extends null
? undefined
: T extends Date
? T
: {
[K in keyof T]: T[K] extends (infer U)[]
? RecursivelyReplaceNullWithUndefined<U>[]
: RecursivelyReplaceNullWithUndefined<T[K]>;
};
export function nullsToUndefined<T>(obj: T): RecursivelyReplaceNullWithUndefined<T> {
if (obj === null) {
return undefined as any;
}
// object check based on: https://stackoverflow.com/a/51458052/6489012
if (obj.constructor.name === "Object") {
for (let key in obj) {
obj[key] = nullsToUndefined(obj[key]) as any;
}
}
return obj as any;
}
Credits go to the typings of this genius: https://github.com/apollographql/apollo-client/issues/2412#issuecomment-755449680
Answer from ysfaran on Stack OverflowThe accepted answer is actually not answering the question since it was asked for a generic way.
Here is one that is similar and will also cast the return type properly:
type RecursivelyReplaceNullWithUndefined<T> = T extends null
? undefined
: T extends Date
? T
: {
[K in keyof T]: T[K] extends (infer U)[]
? RecursivelyReplaceNullWithUndefined<U>[]
: RecursivelyReplaceNullWithUndefined<T[K]>;
};
export function nullsToUndefined<T>(obj: T): RecursivelyReplaceNullWithUndefined<T> {
if (obj === null) {
return undefined as any;
}
// object check based on: https://stackoverflow.com/a/51458052/6489012
if (obj.constructor.name === "Object") {
for (let key in obj) {
obj[key] = nullsToUndefined(obj[key]) as any;
}
}
return obj as any;
}
Credits go to the typings of this genius: https://github.com/apollographql/apollo-client/issues/2412#issuecomment-755449680
The accepted answer is not type safe.
This answer is close, but doesn't handle null inside of nested arrays.
This will replace null with undefined in nested objects and arrays:
type RecursivelyReplaceNullWithUndefined<T> = T extends null
? undefined
: T extends (infer U)[]
? RecursivelyReplaceNullWithUndefined<U>[]
: T extends Record<string, unknown>
? { [K in keyof T]: RecursivelyReplaceNullWithUndefined<T[K]> }
: T;
export function nullsToUndefined<T>(
obj: T,
): RecursivelyReplaceNullWithUndefined<T> {
if (obj === null || obj === undefined) {
return undefined as any;
}
if ((obj as any).constructor.name === 'Object' || Array.isArray(obj)) {
for (const key in obj) {
obj[key] = nullsToUndefined(obj[key]) as any;
}
}
return obj as any;
}
I want to create a type that loops through an object and replaces all nulls with undefined. For example:
// input:
// {
// a: string | null;
// b: string;
// }
// returns:
// {
// a: string | undefined;
// b: string;
// }The best I Have so far is this
export type ReplaceNullWithUndefined<T extends Object> = {
[key in keyof T]: Extract<T[key], null> extends null
? Exclude<T[key], null> | undefined
: T[key];
};
// which with input:
// {
// a: string | null;
// b: string;
// }
// returns:
// {
// a: string | undefined;
// b: string | undefined;
// }Thank you, any help would be amazing
» npm install null-as-undefined
Javascript now supports a null-coalescing operator: ??. It may not be production-ready (consult the support table), but it's certainly safe to use with Node or a transpiler (TypeScript, Babel, etc.).
Per MDN,
The nullish coalescing operator (??) is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
Much as || can provide a "default" value when the left operand is falsey, ?? provides a "default" value if the left operand is null or undefined. You can use this to coerce undefined to null:
// OR operator can coerce 'defined' values
"value" || null; // "value"
0 || null; // null
false || null; // null
"" || null; // null
undefined || null; // null
// The null-coalescing operator will only coerce undefined or null
"value" ?? null; // "value"
0 ?? null; // 0
false ?? null; // false
"" ?? null; // ""
undefined ?? null; // null
An example based on the question:
function mustNotReturnUndefined(mightBeUndefined) { // can return null
// Substitute empty string for null or undefined
let result = processValue(mightBeUndefined ?? "");
// Substitute null for undefined
return result ?? null;
}
undefined || null - or any falsey || null - will return null
Since switching to TypeScript I have been using a lot of optional properties, for example:
type store = {
currentUserId?: string
}
function logout () {
store.currentUserId = undefined
}However my coworkers and I have been discussing whether null is a more appropriate type instead of undefined, like this:
type store = {
currentUserId: string | null
}
function logout () {
store.currentUserId = null
}It seems like the use of undefined in TypeScript differs slightly from in Javascript.
Do you guys/girls use undefined or null more often? And, which of the examples above do you think is better?
Hi folks, i'm a Python/Django developer and just learning Javascript/React, mainly by building stuff and failing at the moment :) This little problem is really giving me a headache to understand.
I'm just trying to make a table from some dummy API data held in a JSON. The data is held in a useState variable (in App.jsx) and then passed as props from App.jsx to my component.
Here is the component. I am getting the error TypeError: Cannot convert undefined or null to object, obviously test is empty when trying to pass it into keys(). But when I simply console log test, it works and I see the array. Why is it not able to access it in my keys variable?
This gives me error. But if I remove the const keys line, I see the array? the aim is to pass keys to map within the JSX and render the table heads.
export default function TaskList(props) {
const test = props.tasks[0]
console.log(test)
const keys = Object.keys(test);
return (
<table className="styled-table">
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
);
}This post explains the differences very well. They are the same in TypeScript as in JavaScript.
As for what you should use: You may define that on your own. You may use either, just be aware of the differences and it might make sense to be consistent.
The TypeScript coding style guide for the TypeScript source code (not an official "how to use TypeScript" guide) states that you should always use undefined and not null: Typescript Project Styleguide.
The value 'undefined' denotes that a variable has been declared, but hasn't been assigned any value. So, the value of the variable is 'undefined'.
On the other hand, 'null' refers to a non-existent object, which basically means 'empty' or 'nothing'.
You can manually assign the value 'undefined' to a variable, but that isn't recommended. So, 'null' is assigned to a variable to specify that the variable doesn't contain any value or is empty. But 'undefined' is used to check whether the variable has been assigned any value after declaration.