writing-functions-and-classes
Skill4 starsChanged 7 days agoMITView on GitHub
Use when declaring any function, method, or class — choosing between a `function` declaration, an arrow and an object method, ordering a class's members, or naming and marking its private members. Applies whenever you write `const x = () =>`, `#field`, a `private` member or a `constructor`.
In this repository12 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- keeping-symbols-localSkill
- naming-filesSkill
- release-dailySkill
- structuring-componentsSkill
- structuring-script-setupSkill
- structuring-utility-filesSkill
- writing-commentsSkill
- writing-composablesSkill
- writing-testsSkill
- writing-typesSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Never bind an arrow to a name.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Writing Functions and Classes
Applies to all code.
A named function is a function declaration
Never bind an arrow to a name.
function formatPercent(value: number) {
return `${value}%`
}const formatPercent = (value: number) => `${value}%`The second is wrong: an arrow assigned to a const is a named function and must be a declaration.
An arrow is only an inline callback
An arrow stays where it is passed — as an argument, or as a value inside an object passed as an argument (a getter or a callback in an options object) — and cannot be a declaration:
const names = users.map((user) => user.name)
useCollapse(panelRef, {disabled: () => props.disabled})A callback that needs a name, or is used twice, becomes a function declaration.
An arrow where lexical this is needed
An arrow is allowed when it needs the surrounding this and is returned from a function (an unsubscribe). The empty fallback ?? (() => {}) is allowed too.
on(event: string, handler: Handler) {
this._handlers.set(event, handler)
return () => this.off(event, handler)
}A function-valued property is a method
In an object you declare, a function-valued property is written as a method:
const formatters = {
json(value: unknown) {
return value ? JSON.stringify(value, null, 2) : ""
},
}Not json: (value) => … or json: function (value) ….
Public before private
Public members and exports come first, private members and helpers last. A <script setup> block follows structuring-script-setup instead (Vue). In a class the fields come first, then the constructor, then the public methods, then the private ones:
export class Counter {
readonly step: number
private _count = 0
constructor(step: number) {
this.step = step
}
increment() {
this._count += this.step
this._notify()
}
private _notify() {
console.log(this._count)
}
}Private class members: private _x
Privacy is the TypeScript private modifier, never the #x syntax. Every private field and method carries the _ prefix, so a private member reads as one at the call site.
A member without the _ prefix is public. A class whose method is private to it is not widened for a test (writing-tests).
Common mistakes
const fn = () => …at module level or inside a function.#fieldinstead ofprivate _field.private fieldwithout the underscore, or_fieldwithoutprivate.- An arrow as a property of an object you declare, when it does not need lexical
this. - A private helper above the public members, or the constructor above the fields.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

