Description
I have an app with two TS (tsconfig.json
) projects:
client
: a browser app which uses the built-in typings from thedom
libserver
: a Node app which uses the types package@types/node
The dependency graph of these projects overlap slightly, as we have components that are server and client rendered. We will refer to files in this overlap as "shared".
I want to be able to access both client-only and server-only constructors in shared files, e.g. window
and global
.
However, this is not possible today, as the server/client TS projects would emit type errors on window
or global
access, respectively.
The only way this will work today is if both client
and server
TS projects specify typings for Node and the browser. However, this is problematic because the typings do not correspond with the environment the code will run in, and mistakes are easily made, such as:
- referencing
window
from code that is only ever ran through Node (server
), wherewindow
does not exist - referencing
window
from code that is ran on through both Node (server
) and the browser (client
), but without guarding for Node, wherewindow
does not exist
Ideally, TypeScript would allow shared files to reference typings in either TS project, but only after guarding first. For example:
// shared/Count.tsx
const getCount = () => {
// `window` access is not available without guarding first
if (typeof window !== 'undefined') {
// `window` access is available here.
return window.localStorage.getItem('count');
} else {
return undefined;
}
};
// React component that is used on the client and server
const Count: SFC<{}> = () => {
const count = getCount();
if (count !== undefined) {
return <div>Count is ${count}</div>;
} else {
return <div>Count unavailable</div>;
}
};
Similarly, Node's global
would only be available after guarding first.