Skip to content

Instantly share code, notes, and snippets.

@terite
Last active May 7, 2020 03:17
Show Gist options
  • Save terite/7a0a0c0799a04829ee2f15e4180ea876 to your computer and use it in GitHub Desktop.
Save terite/7a0a0c0799a04829ee2f15e4180ea876 to your computer and use it in GitHub Desktop.
// @flow strict
// Flow can infer that this program isn't correct, but it shows the error
// in (what I consider) the wrong place. Annotating could move the error
// to a better place (and allow this function to be used from another
// module), but no incantation allows for this to be annotated in a way
// that preserves arity
/* Un-annotated version for your reading pleasure
function timeit(func) {
return function wrapper(...args) {
console.time('timeit')
try {
return func.apply(this, args)
} finally {
console.timeEnd('timeit')
}
}
}
*/
type Fn<TArgs: mixed[], TRet> = (...TArgs) => TRet
function timeit<TArgs: mixed[], TRet>(func: Fn<TArgs, TRet>): Fn<TArgs, TRet> {
return function wrapper(...args) {
console.time('timeit')
try {
return func.apply(this, args)
} finally {
console.timeEnd('timeit')
}
}
}
function strlen(arg: string) { return arg.length }
const timedStrlen = timeit(strlen)
const a: number = timedStrlen('hello')
// Flow can correctly identify this error
const b: number = timedStrlen(42)
// I expect an error here
const c: number = timedStrlen('hello', 'world')
// https://www.typescriptlang.org/play/index.html?ssl=1&ssc=1&pln=24&pc=48#code/GYVwdgxgLglg9mABLAtgUxlAPAFQBYwDOANIgIIBOA5oYmgB5RpgAmtAhmAJ4DaAuqQBKaKAD4AFKEgAuROIB0i9tUKzKNAJSIAvKMTCoWgN4AoRIgD0F8gDc4MFsi4AHGGCqIARFAKFPyOEQAazQ0Z2RfOnp2FGcAGzREQhgUGDjlAIjE4Di4AHdEBDQzS2twILB8pDdEHBc0AGUIChhnKEQiJJS0jKhA1Po0Rxqc-JKKERAKJCloeCQ8inZnZzQKcR8iWXLKvLBSRXllGjUVDVkDRFNzcwgEQjgE+VQ0cQByF8w3jRLzKAouFdfjcJlApjNwBAjis4lwNr5SMdCD8bogAL6IYBudhxWFA1G3e6PNDPFJoACirHenyg32BaJKDIZJlmsAQSX+CTA4mOskI-zcVGMiFB4MQx3kXKoPnRJhMdzA-OQZJYDU5zB0yvQmHE-IoXJ+8vu7XYsjAIBQACM1pqXqr1dy3ng0Li4HSTFZavUmi02ogIJx-XAKBNoHiHMxYMBAZtaGsKMGjYr2pazRbrRRbSq1frmOIACwAJkNnoAklFVtBxUh48HEM6JnJOI4qCJCmA0D8FUqIGmrTbtFqhjmue9na63qQ3nlg3EWN8gA
function timeit<This, Args extends any[], Ret>(func: (...args: Args) => Ret) {
// Avoid typing "this" to keep this example similar to the flow one
// unknown in TypeScript is similar to mixed in flow
return function wrapper(this: unknown, ...args: Args): Ret {
console.time('timeit')
try {
return func.apply(this, args)
} finally {
console.timeEnd('timeit')
}
}
}
function strlen(arg: string) { return arg.length }
const timedStrlen = timeit(strlen)
const a: number = timedStrlen('hello')
// TypeScript can correctly identify this error
const b: number = timedStrlen(42)
// I expect an error here (and get one)
const c: number = timedStrlen('hello', 'world')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment