Skip to content

Instantly share code, notes, and snippets.

@rushkeldon
Last active June 4, 2025 21:38
Show Gist options
  • Save rushkeldon/392409d75f961aebde7345753a3eef7a to your computer and use it in GitHub Desktop.
Save rushkeldon/392409d75f961aebde7345753a3eef7a to your computer and use it in GitHub Desktop.
When prop spreading has left you with doubt as to the shape of the props...
const propMapper = {
typeMap: {},
trueTypeOf(obj) {
const match = {}.toString.call(obj).match(/\s([a-zA-Z]+)/);
const trueType = match?.[1]?.toLowerCase?.() ?? 'unknown';
return trueType === 'asyncgeneratorfunction' ? 'function' : trueType;
},
inferType(value) {
const type = propMapper.trueTypeOf(value);
switch (type) {
case 'string':
case 'number':
case 'boolean':
case 'null':
return type;
case 'function':
return '(...args: any[]) => any';
case 'array':
if (value.length === 0) return 'any[]';
return `${propMapper.inferType(value[0])}[]`;
case 'undefined':
return 'any'; // or skip entirely
case 'object':
if (value?.$$typeof?.toString?.().includes('react'))
return 'React.ReactElement';
return '{}';
default:
return 'any';
}
},
toTypeDefinition(name, shape) {
const lines = Object.entries(shape)
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, type]) => ` ${key}?: ${type};`);
return `type ${name} = {\n${lines.join('\n')}\n};`;
},
normalizePropName(name) {
return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
},
toType(typeName, props) {
if (!propMapper.typeMap[typeName]) {
propMapper.typeMap[typeName] = {};
}
const shape = propMapper.typeMap[typeName];
for (const [key, value] of Object.entries(props)) {
shape[propMapper.normalizePropName(key)] = propMapper.inferType(value);
}
},
logType(typeName) {
const shape = propMapper.typeMap[typeName];
if (!shape) {
console.warn(`No type info recorded for "${typeName}"`);
return;
}
console.log(propMapper.toTypeDefinition(typeName, shape));
},
};
const root = typeof window !== 'undefined' ? window : global;
root.propMapper = propMapper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment