mirror of
https://github.com/foomo/foomo-docs.git
synced 2025-10-16 12:35:40 +00:00
1 line
15 KiB
JavaScript
1 line
15 KiB
JavaScript
"use strict";(self.webpackChunkfoomo=self.webpackChunkfoomo||[]).push([[3964],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>g});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?l(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):l(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},l=Object.keys(e);for(n=0;n<l.length;n++)a=l[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n<l.length;n++)a=l[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var p=n.createContext({}),o=function(e){var t=n.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},c=function(e){var t=o(e.components);return n.createElement(p.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=o(a),d=r,g=u["".concat(p,".").concat(d)]||u[d]||m[d]||l;return a?n.createElement(g,i(i({ref:t},c),{},{components:a})):n.createElement(g,i({ref:t},c))}));function g(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=a.length,i=new Array(l);i[0]=d;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[u]="string"==typeof e?e:r,i[1]=s;for(var o=2;o<l;o++)i[o]=a[o];return n.createElement.apply(null,i)}return n.createElement.apply(null,a)}d.displayName="MDXCreateElement"},3080:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>s,toc:()=>o});var n=a(7462),r=(a(7294),a(3905));const l={sidebar_position:1,toc_max_heading_level:5},i="Value Objects",s={unversionedId:"projects/gotsrpc/service-interfaces/value-objects",id:"projects/gotsrpc/service-interfaces/value-objects",title:"Value Objects",description:"Typically value objects will be serialized / marshalled as JSON. Please refer to this documentation:",source:"@site/docs/projects/gotsrpc/service-interfaces/value-objects.md",sourceDirName:"projects/gotsrpc/service-interfaces",slug:"/projects/gotsrpc/service-interfaces/value-objects",permalink:"/docs/projects/gotsrpc/service-interfaces/value-objects",draft:!1,editUrl:"https://github.com/foomo/foomo-docs/tree/main/foomo/docs/projects/gotsrpc/service-interfaces/value-objects.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1,toc_max_heading_level:5},sidebar:"projectsSidebar",previous:{title:"Service Interfaces",permalink:"/docs/projects/gotsrpc/service-interfaces/"},next:{title:"Errors",permalink:"/docs/projects/gotsrpc/service-interfaces/errors"}},p={},o=[{value:"Scalar types",id:"scalar-types",level:2},{value:"Supported in Go and TypeScript",id:"supported-in-go-and-typescript",level:3},{value:"Numerics / numbers",id:"numerics--numbers",level:3},{value:"Type Aliases",id:"type-aliases",level:3},{value:"Enumerations",id:"enumerations",level:2},{value:"Slices",id:"slices",level:2},{value:"Scalar types",id:"scalar-types-1",level:3},{value:"Other slice type examples",id:"other-slice-type-examples",level:3},{value:"Structs",id:"structs",level:4},{value:"Nested slices",id:"nested-slices",level:4},{value:"Maps / Records",id:"maps--records",level:2},{value:"Scalars",id:"scalars",level:3},{value:"Structs",id:"structs-1",level:3},{value:"Slices",id:"slices-1",level:3},{value:"Map types",id:"map-types",level:2},{value:"Nested map types",id:"nested-map-types",level:2},{value:"Structs / Interfaces",id:"structs--interfaces",level:2},{value:"Field names",id:"field-names",level:3},{value:"Default Go => TypeScript",id:"default-go--typescript",level:4},{value:"Idiomatic field names",id:"idiomatic-field-names",level:4},{value:"Optional and nullable fields",id:"optional-and-nullable-fields",level:3},{value:"Hiding values from the client",id:"hiding-values-from-the-client",level:3},{value:"Union Types",id:"union-types",level:3}],c={toc:o},u="wrapper";function m(e){let{components:t,...a}=e;return(0,r.kt)(u,(0,n.Z)({},c,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"value-objects"},"Value Objects"),(0,r.kt)("p",null,"Typically value objects will be serialized / marshalled as JSON. Please refer to this documentation:"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/encoding/json#Marshal"},"https://pkg.go.dev/encoding/json#Marshal")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"This is just a few basic examples, that show the basics of mapping Go types to idiomatic TypeScript types.")),(0,r.kt)("h2",{id:"scalar-types"},"Scalar types"),(0,r.kt)("h3",{id:"supported-in-go-and-typescript"},"Supported in Go and TypeScript"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Go"),(0,r.kt)("th",{parentName:"tr",align:null},"TypeScript"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"string"),(0,r.kt)("td",{parentName:"tr",align:null},"string")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"bool"),(0,r.kt)("td",{parentName:"tr",align:null},"boolean")))),(0,r.kt)("h3",{id:"numerics--numbers"},"Numerics / numbers"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Go"),(0,r.kt)("th",{parentName:"tr",align:null},"TypeScript"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"int, int8, int16, float32, float64 ..."),(0,r.kt)("td",{parentName:"tr",align:null},"number")))),(0,r.kt)("h3",{id:"type-aliases"},"Type Aliases"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"type Greeting string\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"type Greeting = string;\n")),(0,r.kt)("h2",{id:"enumerations"},"Enumerations"),(0,r.kt)("p",null,"Go does not support enumerations, but ",(0,r.kt)("inlineCode",{parentName:"p"},"gotsrpc")," will translate constants to TypeScripts enums:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},'type Pet string\n\nconst (\n Cat Pet = "cat"\n Dog Pet = "dog"\n Fish Pet = "fish"\n)\n\ntype SeatCount int\n\nconst (\n TwoSeats SeatCount = 2\n FiveSeats SeatCount = 5\n SevenSeats SeatCount = 7\n)\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},'export enum Pet {\n Cat = "cat",\n Dog = "dog",\n Fish = "fish",\n}\n\nexport enum SeatCount {\n FiveSeats = 5,\n SevenSeats = 7,\n TwoSeats = 2,\n}\n')),(0,r.kt)("h2",{id:"slices"},"Slices"),(0,r.kt)("p",null,"Slices are nilable in Go, thus they can be null in TypeScript. They translate to ",(0,r.kt)("inlineCode",{parentName:"p"},"Array<T>|null")," in TypeScript."),(0,r.kt)("h3",{id:"scalar-types-1"},"Scalar types"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"[]string\n[]int\n// other numeric types\n[]bool\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Array<string> | null;\nArray<number> | null;\n// all numeric types are numbers\nArray<boolean> | null;\n")),(0,r.kt)("h3",{id:"other-slice-type-examples"},"Other slice type examples"),(0,r.kt)("h4",{id:"structs"},"Structs"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"[]Car\n[]*Car\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Array<Car> | null;\nArray<Car | null> | null;\n")),(0,r.kt)("h4",{id:"nested-slices"},"Nested slices"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"[][]string\n[][]int\n// ...\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Array<Array<string> | null> | null;\nArray<Array<number> | null> | null;\n// ...\n")),(0,r.kt)("h2",{id:"maps--records"},"Maps / Records"),(0,r.kt)("p",null,"Like slices Go maps are nilable. They translate to ",(0,r.kt)("inlineCode",{parentName:"p"},"Record<K extends keyof any, T>|null")," in TypeScript."),(0,r.kt)("h3",{id:"scalars"},"Scalars"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"map[string]string\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Record<string, string> | null;\n")),(0,r.kt)("h3",{id:"structs-1"},"Structs"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"map[string]*Car\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Record<string, Car | null> | null;\n")),(0,r.kt)("h3",{id:"slices-1"},"Slices"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"map[string][]*Car\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"Record<string, Array<Car | null> | null> | null;\n")),(0,r.kt)("h2",{id:"map-types"},"Map types"),(0,r.kt)("p",null,"Go and TypeScript support map / Record types:"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Scalar types / type aliases are of particular value when using maps, because they can add strong semantics:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"type CarDirectory map[ProductID]*Car\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"type CarDirectory = Record<ProductID, Car | null> | null;\n")),(0,r.kt)("h2",{id:"nested-map-types"},"Nested map types"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"type BrandID string\ntype BrandCarDirectory map[BrandID]map[ProductID]*Car\n// or\ntype BrandCarDirectory map[BrandID]CarDirectory\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"type BrandID = string;\ntype BrandCarDirectory = Record<\n BrandID,\n Record<ProductID, Car | null> | null\n> | null;\n// or\ntype BrandCarDirectory = Record<BrandID, CarDirectory> | null;\n")),(0,r.kt)("h2",{id:"structs--interfaces"},"Structs / Interfaces"),(0,r.kt)("p",null,"Arbitrary Types can be composed in structs."),(0,r.kt)("h3",{id:"field-names"},"Field names"),(0,r.kt)("p",null,"Naming conventions are different between Go and TypeScript. In order to bridge the gap between Go and TypeScript Go struct fields can be ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/encoding/json#Marshal"},"annotated with tags"),". In this way idiomatic naming of fields can be can be provided for both languages and the translation will be automatic."),(0,r.kt)("h4",{id:"default-go--typescript"},"Default Go => TypeScript"),(0,r.kt)("p",null,"Without json tags TypeScript field names will be like in Go, which is not idiomatic for TypeScript."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},"type Car struct {\n GoCase string\n CamelCase string\n SnakeCase string\n}\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"interface Car {\n GoCase:string;\n CamelCase:string;\n SnakeCase:string;\n}\n")),(0,r.kt)("h4",{id:"idiomatic-field-names"},"Idiomatic field names"),(0,r.kt)("p",null,"Json tags allow controlling the name in TypeScript."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},'type Car struct {\n CamelCase string `json:"camelCase"`\n SnakeCase string `json:"snake_case"`\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"interface Car {\n camelCase:string;\n snake_case:string;\n}\n")),(0,r.kt)("h3",{id:"optional-and-nullable-fields"},"Optional and nullable fields"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},'type Basic struct {\n Value string `json:"value"`\n OptionalValue string `json:"optionalValue,omitempty"`\n NullableValue *string `json:"nullableValue"`\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"type Basic interface {\n value:string;\n optionalValue?:string;\n nullableValue:string|null;\n}\n")),(0,r.kt)("h3",{id:"hiding-values-from-the-client"},"Hiding values from the client"),(0,r.kt)("p",null,"The Go json tag ",(0,r.kt)("inlineCode",{parentName:"p"},'`json:"-"`')," on a struct allows it to:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"hide fields from clients"),(0,r.kt)("li",{parentName:"ul"},"prevents clients from setting them in JSON Unmarshalling")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="Go"',title:'"Go"'},'type Basic struct {\n Value string `json:"value"`\n Secret string `json:"-"`\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:'title="TypeScript"',title:'"TypeScript"'},"type Basic interface {\n value:string;\n}\n")),(0,r.kt)("h3",{id:"union-types"},"Union Types"),(0,r.kt)("p",null,"When static types seem to be in the way"))}m.isMDXComponent=!0}}]); |