Skip to content

Instantly share code, notes, and snippets.

View janjakubnanista's full-sized avatar

Ján Jakub Naništa janjakubnanista

  • LayerZero
  • Vancouver
View GitHub Profile
@janjakubnanista
janjakubnanista / 001-simple.ts
Last active May 22, 2020 14:24
Checking for strings and numbers in TypeScript
// You can easily extend this example to check for
// number, boolean, bigint, Function and symbol types
const isString = (value: unknown): value is string => typeof value === 'string';
@janjakubnanista
janjakubnanista / 003-ts-type-checked.ts
Created May 22, 2020 15:04
TypeScript type guards using ts-type-checked
import { isA, typeCheckFor } from 'ts-type-checked';
// Using the typeCheckFor type guard factory
const isString = typeCheckFor<string>();
const isWebSocketMessage = typeCheckFor<WebSocketMessage>();
// Or directly checking a value somewhere in the code
if (isA<string>(value)) return 'Hello String';
if (isA<WebSocketMessage>(value)) return 'Hello Web Socket!';
export function Select<T>(props: SelectProps<T>) {
// It works!
}
@janjakubnanista
janjakubnanista / 002-interface.ts
Last active May 31, 2020 18:29
TypeScript type guards for an interface
// In this made up scenario we are trying to make sure we didn't get
// a corrupted piece of data from a WebSocket
interface WebSocketMessage {
time: number;
text: string;
description?: string;
content: string[];
}
// You could also write this as one looong if statement if you prefer
export function Select<T>(props: SelectProps<T>) {
// This should not be allowed for React components!
return Promise.resolve(null);
}
// And we don't get a warning when defining defaultProps either :/
Select.defaultProps = 7;
// Approach 1: the easy way out
//
// We can just define the return type of our Select
// and make sure it matches the return type of React.FC
function Select<T>(props: SelectProps<T>): React.ReactElement | null {
return null;
}
// Approach 2: diving back in looking for a better way
//
// Approach 1: let's define a prop that turns a value into a human readable label
//
// In this case Select will be rendering the "item container" and will put
// this label into the container
export interface SelectProps<T> {
// ... previous props
labelFromValue: (value: T) => React.ReactNode;
}
// Approach 2: let's define a whole new component type and let it handle the item rendering completely
// Attempt 1: Add generic props to React.FC type
//
// TypeScript will not allow a const to be generic like this!
export const Select: React.FC<SelectProps<T>> = props => {
// Oh no!
}
// Attempt 2: Make the component function generic
//
// JSX parser will colide with TypeScript when trying to do something like this
// Approach 1: the easy way out
//
// We can just define the return type of our Select
// and make sure it matches the return type of React.FC
function Select<T>(props: SelectProps<T>): React.ReactElement | null {
return null;
}
// Unfortunately we can still pass invalid defaultProps :(
Select.defaultProps = 7;
// Approach 2: diving back in looking for a better way
//
// We can create a type that accepts a type parameter
// and puts a constraint on it, in our case we will demand
// the type parameter to be a React.FC
type AssertComponent<C extends React.FC<any>> = C;
// Then we use it in our Select component
function Select<T>(props: SelectProps<T>) {
return null;