javascript - TypeScript funktionella programmeringsmönster för bekväm objektkonstruktion?
Jag har svårt att hitta exempel (videor eller bloggar) på konstruktionsmönster för objekt inom funktionell programmering.
Jag stötte nyligen på nedanstående utdrag av builder-mönstret och jag gillar upplevelsen det ger för att konstruera ett objekt med nästling. När det är ett plattare objekt skulle jag normalt bara använda en enkel objektfabrik med en opts-param för att sprida med standardvärden, men att skicka in en nästlad lista med objekt börjar kännas stökigt.
Finns det FP-mönster som kan göra det bekvämt att komponera ett objekt med inbäddning som nedan samtidigt som man kan anropa vissa metoder n gånger, till exempel addStringOption?
const data = new SlashCommandBuilder()
.setName('echo')
.setDescription('Replies with your input!')
.addStringOption(option =>
option.setName('input')
.setDescription('The input to echo back')
.setRequired(true)
)
.addStringOption(option =>
option.setName('category')
.setDescription('The gif category')
.setRequired(true)
.addChoices(
{ name: 'Funny', value: 'gif_funny' },
{ name: 'Meme', value: 'gif_meme' },
{ name: 'Movie', value: 'gif_movie' },
));
data slutar med att se ut ungefär så här:
{
name: "echo",
description: "Replies with your input!",
options: [
{
name: "input",
description: "The input to echo back",
type: 7, // string option id
required: true,
choices: null,
},
{
name: "category",
description: "The gif category",
required: true,
type: 7,
choices: [
{ name: "Funny", value: "gif_funny" },
{ name: "Meme", value: "gif_meme" },
{ name: "Movie", value: "gif_movie" },
],
},
],
};
Nedan är vad jag leker med. Jag arbetar fortfarande på att lära mig hur man skriver dem i TS, så jag delar JS.
Att tillåta metodkedjning i nedanstående kodsnutt kanske förvränger funktionell programmering för mycket och gör det som objektorienterad programmering, men jag har inte hittat ett alternativ som gör konstruktionen smidigare.
Ett alternativ skulle kunna vara fristående byggare som var och en returnerar en callback som returnerar det uppdaterade tillståndet och sedan kedja ihop dessa byggare, men med vissa byggare som kan anropas n gånger är det svårt att skapa och tillhandahålla kedjan i förväg, och utan punktnotationen som ger intellisense verkar det svårare att veta vilka tillgängliga funktioner som finns att bygga med.
const buildCommand = () => {
// data separate from methods.
let command = {
permissions: ['admin'],
foo: 'bar',
options: [],
};
const builders = {
setGeneralCommandInfo: ({ name, description }) => {
command = { ...command, name, description };
// trying to avoid `this`
return builders;
},
setCommandPermissions: (...permissions) => {
command = { ...command, permissions };
return builders;
},
addStringOption: (callback) => {
const stringOption = callback(buildStringOption());
command = { ...command, options: [...command.options, stringOption] };
return builders;
},
// can validate here
build: () => command,
};
return builders;
};
const buildStringOption = () => {
let stringOption = {
choices: null,
type: 7,
};
const builders = {
setName: (name) => {
stringOption = { ...stringOption, name };
return builders;
},
setDescription: (description) => {
stringOption = { ...stringOption, description };
return builders;
},
addChoices: (choices) => {
stringOption = { ...stringOption, choices };
return builders;
},
build: () => stringOption,
};
return builders;
};
const command1 = buildCommand()
.setGeneralCommandInfo({ name: 'n1', description: 'd1' })
.setCommandPermissions('auditor', 'moderator')
.addStringOption((option) =>
option.setName('foo').setDescription('bar').build()
)
.addStringOption((option) =>
option
.setName('baz')
.setDescription('bax')
.addChoices([
{ name: 'Funny', value: 'gif_funny' },
{ name: 'Meme', value: 'gif_meme' },
])
.build()
)
.build();
console.log(command1);
Svar #1
Varför inte helt enkelt skapa och använda datakonstruktörer?
const SlashCommand = (name, description, options) =>
({ name, description, options });
const StringOption = (name, description, required, type = 7, choices = null) =>
({ name, description, required, type, choices });
const Choice = (name, value) => ({ name, value });
const data = SlashCommand('echo', 'Replies with your input!', [
StringOption('input', 'The input to echo back', true),
StringOption('category', 'The gif category', true, undefined, [
Choice('Funny', 'gif_funny'),
Choice('Meme', 'gif_meme'),
Choice('Movie', 'gif_movie')
])
]);
console.log(data);TypeScript-lekplats exempel
Du kan inte få det mer funktionellt än så här. Intellisense kommer också att hjälpa dig med konstruktörsargumenten.
