Skip to content

Groupguanfang/function-decorator

Repository files navigation

Function Decorator Support

English | 简体中文

这是一个用于给现有的TypeScript添加函数装饰器支持的仓库。

🎯 项目目标

很简单: 支持有名字的函数添加装饰器。如:

function hello(target: (...args: any[]) => any, ctx: FunctionDecoratorContext) {
  console.log('Decorated!')
}

// 正确的用法
@hello
export function test() {
  console.log('hello')
}

// 错误的用法
function test() {
  @hello // 这是不被允许的❗️
  return function () {}
}

你可以看到,hello函数就是一个装饰器。装饰器接收了两个参数:

  • target: 被装饰的函数
  • ctx: 装饰器上下文

装饰器的签名,参考了TC39函数和object literal装饰器提案,如下:

interface FunctionDecoratorContext {
  kind: 'function'
  // 被装饰的函数名
  name: string
  // 被装饰的函数的元数据
  metadata: object
  // 添加初始化器,将在被装饰函数调用前调用
  addInitializer: (initializer: () => void) => void
}

type FunctionDecorator = (
  // 被装饰的函数
  target: (...args: any[]) => any,
  // 装饰器上下文
  ctx: FunctionDecoratorContext,
) => void

只要遵循这个签名的函数都可以作为一个函数装饰器来使用。

✒️ ESLint

仓库提供了一个eslint包,如果遇到eslint报错提示“装饰器不能出现在这里”,可以安装这个包来解决。

pnpm add -D @function-decorator/eslint

然后修改你的eslint配置,如果使用antfu的@antfu/eslint-config,那么只需要在eslint.config.js中添加一点点东西即可:

import antfu from '@antfu/eslint-config'
import { overrideParser } from '@function-decorator/eslint'

export default antfu().override('antfu/typescript/parser', overrideParser)

这相当于重写了@antfu/eslint-config的typescript解析器对象。

🍽️ TypeScript

如果遇到TS2306错误,仓库提供了一个vscode插件以供忽略这个错误,直接从vscode插件市场安装即可:

VSCode插件市场链接:https://marketplace.visualstudio.com/items?itemName=NailyZero.vscode-naily-function-decorator

🧩 插件

仓库提供了一个unplugin插件,支持webpackviterollupesbuildrolldownrspack等构建工具。

pnpm add -D @function-decorator/unplugin

然后你就可以在各种构建工具的配置文件中使用该插件了:

Vite
// vite.config.ts
import FnDecorator from '@function-decorator/unplugin/vite'

export default defineConfig({
  plugins: [
    FnDecorator({ /* options */ }),
  ],
})

Example: playground/


Rollup
// rollup.config.js
import FnDecorator from '@function-decorator/unplugin/rollup'

export default {
  plugins: [
    FnDecorator({ /* options */ }),
  ],
}


Webpack
// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require('@function-decorator/unplugin/webpack')({ /* options */ })
  ]
}


Nuxt
// nuxt.config.js
export default defineNuxtConfig({
  modules: [
    ['@function-decorator/unplugin/nuxt', { /* options */ }],
  ],
})

This module works for both Nuxt 2 and Nuxt Vite


Vue CLI
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require('@function-decorator/unplugin/webpack')({ /* options */ }),
    ],
  },
}


esbuild
import FnDecorator from '@function-decorator/unplugin/esbuild'
// esbuild.config.js
import { build } from 'esbuild'

build({
  plugins: [FnDecorator()],
})


🧠 启发

感谢以下仓库,让我有了这个想法,并基本实现了它:

About

﹫Function decorator support for TypeScript 🤩

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published