kitten's notebooks

  • Calling a component with hooks - /kitten/calling-a-component-with-hooks
    Last edited 5 years ago
    const React = require('react'); const ReactDOM = require('react-dom/server'); const SomeComponent = () => { React.useEffect(() => {}, []); return React.createElement('div'); }; ReactDOM.renderToString(React.createElement(SomeComponent)); console.log('has prototype?', !!SomeComponent.prototype); SomeComponent();
  • Poor man's RunRunRunTypes - /kitten/runrunruntypes
    Last edited 5 years ago
    const { parse } = require('@babel/parser'); const makeInvariantFromNode = node => { switch (node.type) { case 'BooleanLiteralTypeAnnotation': case 'StringLiteralTypeAnnotation': case 'NumberLiteralTypeAnnotation': { const { value } = node; return x => x === value; } case 'StringTypeAnnotation': return x => typeof x === 'string'; case 'NumberTypeAnnotation': return x => typeof x === 'number'; case 'BooleanTypeAnnotation': return x => typeof x === 'boolean'; case 'NullLiteralTypeAnnotation': return x => x === null; case 'VoidTypeAnnotation': return x => x === undefined; case 'NullableTypeAnnotation': { const inner = makeInvariantFromNode(node.typeAnnotation); return val => val === null || val === undefined || inner(val); } case 'ArrayTypeAnnotation': { const inner = makeInvariantFromNode(node.elementType); return val => Array.isArray(val) && val.every(inner); } case 'GenericTypeAnnotation': { const { name } = node.id; if (name === 'Function') return val => typeof val === 'function' else if (name === 'Object') return val => typeof val === 'object' else return val => typeof val === 'object' && val.constructor.name === name; } case 'IntersectionTypeAnnotation': { const inner = node.types.map(makeInvariantFromNode); return val => inner.every(i => i(val)); } case 'UnionTypeAnnotation': { const inner = node.types.map(makeInvariantFromNode); return val => inner.some(i => i(val)); } case 'TupleTypeAnnotation': { const values = node.types.map(makeInvariantFromNode);      return val => Array.isArray(val) && val.length === values.length && val.every((x, i) => values[i](x)); } case 'ObjectTypeAnnotation': { const properties = node.properties .filter(n => n.type === 'ObjectTypeProperty') .map(n => [n.key.name, makeInvariantFromNode(n.value)]); return val => typeof val === 'object' && properties.every(([key, inner]) => inner(val[key])); } case 'AnyTypeAnnotation': return () => true; default:      throw new TypeError(`Unsupported type annotation ${node.type}`); } }; const makeInvariantForFn = (paramTypes, returnType) => fn => { const paramSize = paramTypes.length; const paramInvariants = paramTypes.map(makeInvariantFromNode); const returnInvariant = makeInvariantFromNode(returnType); if (paramSize !== fn.length) { throw new TypeError('Arity of type annotation and actual arguments do not match'); } return (...args) => { if (paramSize !== args.length) { throw new TypeError('Arity of type annotation and passed arguments do not match'); } for (let i = 0; i < paramSize; i++) { if (!paramInvariants[i](args[i])) { const typeReadable = paramTypes[i].type.replace('Annotation', ''); throw new TypeError(`Invalid ${i + 1}. argument, expected ${typeReadable}.`); } } const res = fn(...args); if (!returnInvariant(res)) { const typeReadable = returnType.type.replace('Annotation', ''); throw new TypeError(`Invalid return value, expected ${typeReadable}.`); } return res; }; }; const sig = def => { const input = `type x = ${def}`; const { program: { body } } = parse(input, { plugins: ['flow'] }); return body[0]; /* const node = body[0]; if (!node || !node.right || node.right.type !== 'FunctionTypeAnnotation') { throw new TypeError(`Expected valid Flow function annotation.`); } const { params, returnType } = node.right; const paramTypes = params.map(n => n.typeAnnotation); console.log(paramTypes); return makeInvariantForFn(paramTypes, returnType); */ }; sig` { message: ?string } ` // fun('test')
  • Untitled - /kitten/5c489ca4e6490900122e9ecfb
    Last edited 5 years ago
    const leftpad = require('leftpad'); const toFixedLong = (input, decimalPoints = 1) => { const floor = Math.floor(input) let x = floor let output = '' while (x >= 1000) { output = ',' + leftpad(x % 1000, 3, '0') + output; x = Math.floor(x / 1000); } return '' + x + output + (input - floor).toFixed(decimalPoints).slice(1); } const input = 1234000000000000.245 // 1,234,000,000,000,000.245 const inputB = 1.3986383939661338e+308 console.log(toFixedLong(input)) console.log(toFixedLong(inputB))