{"id":13522704,"url":"https://github.com/gohanlon/swift-memberwise-init-macro","last_synced_at":"2026-04-02T19:11:23.087Z","repository":{"id":201407628,"uuid":"685701175","full_name":"gohanlon/swift-memberwise-init-macro","owner":"gohanlon","description":"Swift Macro for enhanced automatic inits.","archived":false,"fork":false,"pushed_at":"2026-03-30T20:19:22.000Z","size":222,"stargazers_count":185,"open_issues_count":5,"forks_count":22,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-30T21:20:56.455Z","etag":null,"topics":["swift","swift-macros","swift-package-manager","swift-syntax"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gohanlon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-08-31T20:11:44.000Z","updated_at":"2026-03-30T09:42:47.000Z","dependencies_parsed_at":"2024-04-19T21:29:52.100Z","dependency_job_id":"0a4eaf74-1a2d-47fe-b484-18e3e4d0fec8","html_url":"https://github.com/gohanlon/swift-memberwise-init-macro","commit_stats":null,"previous_names":["gohanlon/swift-memberwise-init-macro"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/gohanlon/swift-memberwise-init-macro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gohanlon%2Fswift-memberwise-init-macro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gohanlon%2Fswift-memberwise-init-macro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gohanlon%2Fswift-memberwise-init-macro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gohanlon%2Fswift-memberwise-init-macro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gohanlon","download_url":"https://codeload.github.com/gohanlon/swift-memberwise-init-macro/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gohanlon%2Fswift-memberwise-init-macro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314090,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["swift","swift-macros","swift-package-manager","swift-syntax"],"created_at":"2024-08-01T06:00:51.381Z","updated_at":"2026-04-02T19:11:23.078Z","avatar_url":"https://github.com/gohanlon.png","language":"Swift","funding_links":[],"categories":["Misc","Swift","Developer Tools"],"sub_categories":["Vim"],"readme":"# @MemberwiseInit\n\n![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/gohanlon/swift-memberwise-init-macro/ci.yml)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fgohanlon%2Fswift-memberwise-init-macro%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/gohanlon/swift-memberwise-init-macro)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fgohanlon%2Fswift-memberwise-init-macro%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/gohanlon/swift-memberwise-init-macro)\n\nA Swift Macro for enhanced automatic memberwise initializers, greatly reducing manual boilerplate:\n\n* **~1,100 deletions** to [Point-Free’s Website with MemberwiseInit][pointfreeco-website-memberwiseinit].\n* **~1,300 deletions** to [Point-Free’s Isowords with MemberwiseInit][pointfreeco-isowords-memberwiseinit].\n\n![swift-memberwise-init-hero04](https://github.com/gohanlon/swift-memberwise-init-macro/assets/3375/5aab978d-fe31-4d2a-968a-b540adbd1355)\n\nInformed by explicit developer cues, MemberwiseInit can more often automatically provide your intended memberwise `init`, while maintaining a safe-by-default standard in line with [Swift’s memberwise initializers][swifts-memberwise-init].\n\n\u003e [!IMPORTANT]\n\u003e `@MemberwiseInit` is a Swift Macro requiring **swift-tools-version: 5.9** or later (**Xcode 15** onwards).\n\n* [Quick start](#quick-start)\n* [Quick reference](#quick-reference)\n* [Features and limitations](#features-and-limitations)\n  * [Custom `init` parameter labels](#custom-init-parameter-labels)\n  * [Infer type from property initialization expressions](#infer-type-from-property-initialization-expressions)\n  * [Default values, even for `let` properties](#default-values-even-for-let-properties)\n  * [Explicitly ignore properties](#explicitly-ignore-properties)\n  * [Attributed properties are ignored by default, but includable](#attributed-properties-are-ignored-by-default-but-includable)\n  * [Support for property wrappers](#support-for-property-wrappers)\n  * [Automatic `@escaping` for closure types (usually)](#automatic-escaping-for-closure-types-usually)\n  * [Experimental: Unchecked memberwise initialization](#experimental-unchecked-memberwise-initialization)\n  * [Deprecated: Deunderscore parameter names](#deprecated-deunderscore-parameter-names)\n  * [Experimental: Defaulting optionals to nil](#experimental-defaulting-optionals-to-nil)\n  * [Tuple destructuring in property declarations isn’t supported (yet)](#tuple-destructuring-in-property-declarations-isnt-supported-yet)\n* [Background](#background)\n* [License](#license)\n\n## Quick start\n\nTo use MemberwiseInit:\n\n1. **Installation**\n   \u003cbr\u003e In Xcode, add MemberwiseInit with: `File` → `Add Package Dependencies…` and input the package URL:\n\n   \u003e `https://github.com/gohanlon/swift-memberwise-init-macro`\n\n   Or, for SPM-based projects, add it to your package dependencies:\n\n   ```swift\n   dependencies: [\n     .package(url: \"https://github.com/gohanlon/swift-memberwise-init-macro\", from: \"0.6.0\")\n   ]\n   ```\n\n   And then add the product to all targets that use MemberwiseInit:\n\n   ```swift\n   .product(name: \"MemberwiseInit\", package: \"swift-memberwise-init-macro\"),\n   ```\n\n2. **Import \u0026 basic usage**\n   \u003cbr\u003e After importing MemberwiseInit, add `@MemberwiseInit(.public)` before your struct definition. This provides an initializer with public access, or, if any properties are more restrictive, the macro will not compile and will emit an error diagnostic. Here, `age` being private makes the macro emit an error:\n\n   ```swift\n   @MemberwiseInit(.public)\n   public struct Person {\n     public let name: String\n     private var age: Int? = nil\n   //┬──────\n   //╰─ 🛑 @MemberwiseInit(.public) would leak access to 'private' property\n   //   ✏️ Add '@Init(.public)'\n   //   ✏️ Replace 'private' access with 'public'\n   //   ✏️ Add '@Init(.ignore)'\n   }\n   ```\n\n   Tell MemberwiseInit to ignore `age` with `@Init(.ignore)`:\n\n   ```swift\n   @MemberwiseInit(.public)\n   public struct Person {\n     public let name: String\n     @Init(.ignore) private var age: Int? = nil\n   }\n   ```\n\n   Alternatively, you can use `@Init(.public)` to include and expose `age` publicly in the `init`:\n\n   ```swift\n   @MemberwiseInit(.public)\n   public struct Person {\n     public let name: String\n     @Init(.public) private var age: Int? = nil\n   }\n   ```\n\n## Quick reference\n\nMemberwiseInit includes three macros:\n\n### `@MemberwiseInit`\n\nAttach to a struct to automatically provide it with a memberwise initializer.\n\n* `@MemberwiseInit`\n  \u003cbr\u003e Provide an internal memberwise `init`.\n\n* `@MemberwiseInit(.public)`\n  \u003cbr\u003e Provide a memberwise `init` at the provided access level. Valid access levels: `.private`, `.fileprivate`, `.internal`, `.package`, `.public`, `.open`.\n\n### `@Init`\n\nAttach to the property declarations of a struct that `@MemberwiseInit` is providing an `init` for.\n\n* `@Init`\n  \u003cbr\u003e Include a property that would otherwise be ignored, e.g., attributed properties such as SwiftUI’s `@State` properties.\n\n* `@Init(.ignore)`\n  \u003cbr\u003e Ignore that member property. The access level of an ignored property won’t cause the macro to fail, and the property won’t be included in the `init`. *Note: Ignored properties must be initialized elsewhere.*\n\n* `@Init(.public)`\n  \u003cbr\u003e For the provided `init`, consider the property as having a different access level than its declared access level. Valid access levels: `.private`, `.fileprivate`, `.internal`, `.package`, `.public`, `.open`.\n\n* `@Init(default: 42)`\n  \u003cbr\u003e Specifies a default parameter value for the property’s `init` argument, necessary for defaulting `let` properties.\n\n* `@Init(escaping: true)`\n  \u003cbr\u003e To avoid compiler errors when a property’s `init` argument can’t automatically be `@escaped`, e.g. when a property’s type uses a typealias that represents a closure.\n\n* `@Init(label: String)`\n  \u003cbr\u003e Assigns a custom parameter label in the provided `init`.\n  * Use `@Init(label: \"_\")` to make the `init` parameter label-less.\n  * Diagnostic errors arise from invalid labels, when misapplied to declarations having multiple bindings, or from naming conflicts among properties included in the `init`. (Ignored properties don’t cause conflicts.)\n\n* `@Init(.public, default: { true }, escaping: true, label: \"where\")`\n  \u003cbr\u003e All arguments can be combined.\n\n### `@InitWrapper(type:)`\n\n* `@InitWrapper(type: Binding\u003cString\u003e.self)`\n  \u003cbr\u003e Apply this attribute to properties that are wrapped by a property wrapper and require direct initialization using the property wrapper’s type.\n\n  ```swift\n  @MemberwiseInit\n  struct CounterView: View {\n    @InitWrapper(type: Binding\u003cBool\u003e.self)\n    @Binding var isOn: Bool\n\n    var body: some View { … }\n  }\n  ```\n\n  \u003e **Note**\n  \u003e The above `@InitWrapper` is functionally equivalent to the following `@InitRaw` configuration:\u003cbr\u003e\n  \u003e `@InitRaw(assignee: \"self._isOn\", type: Binding\u003cBool\u003e.self)`.\n\n### Etcetera\n\n* `@InitRaw`\n  \u003cbr\u003e Attach to property declarations to directly configure MemberwiseInit.\n\n  ```swift\n  public macro InitRaw(\n    _ accessLevel: AccessLevelConfig? = nil,\n    assignee: String? = nil,\n    default: Any? = nil,\n    escaping: Bool? = nil,\n    label: String? = nil,\n    type: Any.Type? = nil\n  )\n  ```\n\n* `@MemberwiseInit(_optionalsDefaultNil: true)` *(experimental)*\n  \u003cbr\u003e When set to `true`, give all optional properties a default `init` parameter value of `nil`. For non-public initializers, optional `var` properties default to `nil` unless this parameter is explicitly set to `false`.\n\n* `@MemberwiseInit(_deunderscoreParameters: true)` *(deprecated, use `@Init(label:)` instead)*\n  \u003cbr\u003e Drop underscore prefix from generated `init` parameter names, unless doing so would result in a naming conflict. Ignored properties won't contribute to conflicts, and overridable using `@Init(label:)`.\n\n* `@MemberwiseInit` on  `actor`, `class` *(experimental)*\n  \u003cbr\u003e Attachable to actor and class.\n\n* `@_UncheckedMemberwiseInit` *(experimental)*\n  \u003cbr\u003e Generate a memberwise initializer for all properties, regardless of access level, with reduced compile-time safety checks (compared to `@MemberwiseInit`).\n\n## Features and limitations\n\n### Custom `init` parameter labels\n\nTo control the naming of parameters in the provided initializer, use `@Init(label: String)`. Tip: For a label-less/wildcard parameter, use `@Init(label: \"_\")`.\n\n#### Explanation\n\nCustomize your initializer parameter labels with `@Init(label: String)`:\n\n1. **Label-less/wildcard parameters**\n\n   ```swift\n   @MemberwiseInit\n   struct Point2D {\n     @Init(label: \"_\") let x: Int\n     @Init(label: \"_\") let y: Int\n   }\n   ```\n\n   Yields:\n\n   ```swift\n   init(\n     _ x: Int,\n     _ y: Int\n   ) {\n     self.x = x\n     self.y = y\n   }\n   ```\n\n2. **Custom parameter labels**\n\n   ```swift\n   @MemberwiseInit\n   struct Receipt {\n     @Init(label: \"for\") let item: String\n   }\n   ```\n\n   Yields:\n\n   ```swift\n   init(\n     for item: String  // 👈\n   ) {\n     self.item = item\n   }\n   ```\n\n### Infer type from property initialization expressions\n\nExplicit type annotations are not required when properties are initialized with an expression whose syntax implies type information, e.g., most Swift literals:\n\n```swift\n@MemberwiseInit\nstruct Example {\n  var count = 0  // 👈 `Int` is inferred\n}\n```\n\n#### Explanation\n\nExplicit type specification can feel redundant. Helpfully, Swift’s memberwise initializer infers type from arbitrary expressions.\n\nMemberwiseInit, as a Swift Macro, operates at the syntax level and doesn’t inherently understand type information. Still, many expressions which imply type from their syntax alone are supported, including all of the following:\n\n```swift\n@MemberwiseInit\npublic struct Example\u003cT: CaseIterable\u003e {\n  var string = \"\", int = 0\n  var boolTrue = true\n\n  var mixedDivide = 8.0 / 4  // Double\n  var halfOpenRange = 1.0..\u003c5  // Range\u003cDouble\u003e\n\n  var arrayTypeInit = [T]()\n  var arrayIntLiteral = [1, 2, 3]\n  var arrayPromoted = [1, 2.0]  // [Double]\n  var nestedArray = [[1, 2], [20, 30]]  // [[Int]]\n\n  var dictionaryTypeInit = [String: T]()\n  var dictionaryLiteral = [\"key1\": 1, \"key2\": 2]\n  var dictionaryPromoted = [1: 2.0, 3.0: 4]  // [Double: Double]\n  var nestedDictionary = [\"key1\": [\"subkey1\": 10], \"key2\": [\"subkey2\": 20]]  // [String: [String: Int]]\n\n  var tuple = (1, (\"Hello\", true))\n  var value = T.allCases.first as T?\n\n  var nestedMixed = ((1 + 2) * 3) \u003e= (4 / 2) \u0026\u0026 ((true || false) \u0026\u0026 !(false))  // Bool\n\n  var bitwiseAnd = 0b1010 \u0026 0b0101\n  var leftShift = 1 \u003c\u003c 2\n  var bitwiseNotInt = ~0b0011\n\n  var intBinary = 0b01010101\n  var intOctal = 0o21\n  var intHex = 0x1A\n  var floatExponential = 1.25e2  // Double\n  var floatHex = 0xC.3p0  // Double\n\n  var arrayAs = [1, \"foo\", 3] as [Any]\n  var dictionaryAs = [\"foo\": 1, 3: \"bar\"] as [AnyHashable: Any]\n}\n```\n\n### Default values, even for `let` properties\n\nUse `@Init(default: Any)` to set default parameter values in the initializer. This is particularly useful for `let` properties, which otherwise cannot be defaulted after declaration. For `var` properties, consider using a declaration initializer (e.g., `var number = 0`) as a best practice.\n\n#### Explanation\n\nMemberwiseInit, like Swift, utilizes variable initializers to assign default values to `var` properties:\n\n```swift\n@MemberwiseInit\nstruct UserSettings {\n  var theme = \"Light\"\n  var notificationsEnabled = true\n}\n```\n\nThis yields:\n\n```swift\ninternal init(\n  theme: String = \"Light\",\n  notificationsEnabled: Bool = true\n) {\n  self.theme = theme\n  self.notificationsEnabled = notificationsEnabled\n}\n```\n\nFor `let` properties, `@Init(default:)` enables setting default values in the initializer:\n\n```swift\n@MemberwiseInit\nstruct ButtonStyle {\n  @Init(default: Color.blue) let backgroundColor: Color\n  @Init(default: Font.system(size: 16)) let font: Font\n}\n```\n\nThis yields:\n\n```swift\ninternal init(\n  backgroundColor: Color = Color.blue,\n  font: Font = Font.system(size: 16)\n) {\n  self.backgroundColor = backgroundColor\n  self.font = font\n}\n```\n\n### Explicitly ignore properties\n\nUse `@Init(.ignore)` to exclude a property from MemberwiseInit’s initializer; ensure ignored properties are otherwise initialized to avoid compiler errors.\n\n#### Explanation\n\nThe `@Init(.ignore)` attribute excludes properties from the initializer, potentially allowing MemberwiseInit to produce a more accessible initializer for the remaining properties.\n\nFor example:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  @Init(.ignore) private var age: Int? = nil  // 👈 Ignored and given a default value\n}\n```\n\nBy marking `age` as ignored, MemberwiseInit creates a public initializer without the `age` parameter:\n\n```swift\npublic init(\n  name: String\n) {\n  self.name = name\n}\n```\n\nIf `age` weren't marked as ignored, MemberwiseInit would fail to compile and provide a diagnostic.\n\n\u003e **Note**\n\u003e In line with Swift’s memberwise initializer, MemberwiseInit automatically ignores `let` properties with assigned default values, as reassigning such properties within the initializer would be invalid.\n\n### Attributed properties are ignored by default, but includable\n\nIf MemberwiseInit ignores an attributed property and causes a compiler error, you have two immediate remedies:\n\n1. Assign a default value to the property.\n2. Explicitly include the property in the initializer using the `@Init` annotation.\n\n#### Explanation\n\nUnlike the compiler’s default behavior, MemberwiseInit takes a more cautious approach when dealing with member properties that have attributes attached.\n\nFor a SwiftUI-based illustration, let’s look at a view without MemberwiseInit:\n\n```swift\nimport SwiftUI\nstruct MyView: View {\n  @State var isOn: Bool\n\n  var body: some View { … }\n}\n```\n\nSwift provides the following internal memberwise `init`:\n\n```swift\ninternal init(\n  isOn: Bool\n) {\n  self.isOn = isOn\n}\n```\n\nHowever, initializing `@State` properties in this manner is a common pitfall in SwiftUI. The `isOn` state is only assigned upon the initial rendering of the view, and this assignment doesn’t occur on subsequent renders. To safeguard against this, MemberwiseInit defaults to ignoring attributed properties:\n\n```swift\nimport SwiftUI\n@MemberwiseInit(.internal)  // 👈\nstruct MyView: View {\n  @State var isOn: Bool\n\n  var body: some View { … }\n}\n```\n\nThis leads MemberwiseInit to provided the following initializer:\n\n```swift\ninternal init() {\n}  // 🛑 Compiler error:↵\n// Return from initializer without initializing all stored properties\n```\n\nFrom here, you have two alternatives:\n\n1. **Assign a default value**\n   \u003cbr\u003e Defaulting the property to a value makes the provided `init` valid, as the provided `init` no longer needs to initialize the property.\n\n   ```swift\n   import SwiftUI\n   @MemberwiseInit(. internal)\n   struct MyView: View {\n     @State var isOn: Bool = false  // 👈 Default value provided\n\n     var body: some View { … }\n   }\n   ```\n\n   The resulting `init` is:\n\n   ```swift\n   internal init() {\n   }  // 🎉 No error, all stored properties are initialized\n   ```\n\n2. **Use `@Init` annotation**\n   \u003cbr\u003e If you understand the behavior the attribute imparts, you can explicitly mark the property with `@Init` to include it in the initializer.\n\n   ```swift\n   import SwiftUI\n   @MemberwiseInit(.internal)\n   struct MyView: View {\n     @Init @State var isOn: Bool  // 👈 `@Init`\n\n     var body: some View { … }\n   }\n   ```\n\n   This yields:\n\n   ```swift\n   internal init(\n     isOn: Bool\n   ) {\n     self.isOn = isOn\n   }\n   ```\n\n### Support for property wrappers\n\nApply `@InitWrapper` to properties that are wrapped by a property wrapper and require direct initialization using the property wrapper’s type. For example, here’s a simple usage with SwiftUI’s `@Binding`:\n\n```swift\nimport SwiftUI\n\n@MemberwiseInit\nstruct CounterView: View {\n  @InitWrapper(type: Binding\u003cInt\u003e.self)\n  @Binding var count: Int\n\n  var body: some View { … }\n}\n```\n\nThis yields:\n\n```swift\ninternal init(\n  count: Binding\u003cInt\u003e\n) {\n  self._count = count\n}\n```\n\n### Automatic `@escaping` for closure types (usually)\n\nMemberwiseInit automatically marks closures in initializer parameters as `@escaping`. If using a typealias for a closure, explicitly annotate the property with `@Init(escaping: true)`.\n\n#### Explanation\n\nSwift Macros operate at the syntax level and don’t inherently understand type information. MemberwiseInit will add `@escaping` for closure types, provided that the closure type is directly declared as part of the property. Fortunately, this is the typical scenario.\n\nIn contrast, Swift’s memberwise initializer has the advantage of working with type information. This allows it to recognize and add `@escaping` even when the closure type is “obscured” within a typealias.\n\nConsider the following struct:\n\n```swift\npublic struct TaskRunner {\n  public let onCompletion: () -\u003e Void\n}\n```\n\nThrough observation (or by delving into the compiler’s source code), we can see that Swift automatically provides the following internal `init`:\n\n```swift\ninternal init(\n  onCompletion: @escaping () -\u003e Void  // 🎉 `@escaping` automatically\n) {\n  self.onCompletion = onCompletion\n}\n```\n\nNow, with MemberwiseInit:\n\n```swift\n@MemberwiseInit  // 👈\npublic struct TaskRunner {\n  public let onCompletion: () -\u003e Void\n}\n```\n\nwe get the same `init`, which we can inspect using Xcode’s “Expand Macro” command:\n\n```swift\ninternal init(\n  onCompletion: @escaping () -\u003e Void  // 🎉 `@escaping` automatically\n) {\n  self.onCompletion = onCompletion\n}\n```\n\nAnd we can have MemberwiseInit provide a public `init`:\n\n```swift\n@MemberwiseInit(.public)  // 👈 `.public`\npublic struct TaskRunner {\n  public let onCompletion: () -\u003e Void\n}\n```\n\nThis yields:\n\n```swift\npublic init(  // 🎉 `public`\n  onCompletion: @escaping () -\u003e Void\n) {\n  self.onCompletion = onCompletion\n}\n```\n\nNow, suppose the type of `onCompletion` got more complex and we decided to extract a typealias:\n\n```swift\npublic typealias CompletionHandler = @Sendable () -\u003e Void\n\n@MemberwiseInit(.public)\npublic struct TaskRunner: Sendable {\n  public let onCompletion: CompletionHandler\n}\n```\n\nBecause Swift Macros don’t inherently understand type information, MemberwiseInit cannot “see” that `CompletionHandler` represents a closure type that needs to be marked `@escaping`. This leads to a compiler error:\n\n```swift\npublic init(\n  onCompletion: CompletionHandler  // 👈 Missing `@escaping`!\n) {\n  self.onCompletion = onCompletion  // 🛑 Compiler error:↵\n  // Assigning non-escaping parameter 'onCompletion' to an @escaping closure\n}\n```\n\nTo address this, when using a typealias for closures, you must explicitly mark the property with `@Init(escaping: true)`:\n\n```swift\npublic typealias CompletionHandler = @Sendable () -\u003e Void\n\n@MemberwiseInit(.public)\npublic struct TaskRunner: Sendable {\n  @Init(escaping: true) public let onCompletion: CompletionHandler  // 👈\n}\n```\n\nwhich results in the following valid and inspectable public `init`:\n\n```swift\npublic init(\n  onCompletion: @escaping CompletionHandler  // 🎉 Correctly `@escaping`\n) {\n  self.onCompletion = onCompletion\n}\n```\n\n### Experimental: Unchecked memberwise initialization\n\n`@_UncheckedMemberwiseInit` is an experimental macro that bypasses compile-time safety checks and strict access control enforcement. It generates an initializer for all properties of a type, regardless of their declared access levels. Use it judiciously.\n\nKey characteristics:\n\n- Generates an initializer that includes all properties, regardless of their declared access levels\n- Includes attributed properties by default (differs from `@MemberwiseInit`)\n- Follows the same usage pattern as `@MemberwiseInit`\n\nExample:\n\n```swift\n@_UncheckedMemberwiseInit(.public)\npublic struct APIResponse: Codable {\n  public let id: String\n  @Monitored internal var statusCode: Int\n  private var rawResponse: Data\n\n  // Computed properties and methods...\n}\n```\n\nThis yields a public initializer that includes all properties, regardless of their access level or attributes. Unlike `@MemberwiseInit`, this macro doesn't require `@Init` annotations or any other explicit opt-ins. The resulting initializer is:\n\n```swift\npublic init(\n  id: String,\n  statusCode: Int,\n  rawResponse: Data\n) {\n  self.id = id\n  self.statusCode = statusCode\n  self.rawResponse = rawResponse\n}\n```\n\n### Deprecated: Deunderscore parameter names\n\n\u003e **Warning**\n\u003e `_deunderscoreParameters` is deprecated and will be removed in version 1.0. Use `@Init(label:)` on individual properties instead.\n\nSet `@MemberwiseInit(_deunderscoreParameters: true)` to strip the underscore prefix from properties when generating initializer parameter names. If you wish to maintain the underscore or provide a custom label on a particular property, use `@Init(label: String)`.\n\nIf the removal of the underscore would lead to a naming conflict among the properties included in the initializer, MemberwiseInit will not strip the underscore. (Ignored properties won’t contribute to conflicts.)\n\n#### Explanation\n\nIn Swift, properties prefixed with an underscore are conventionally used as internal storage or backing properties. Setting `_deunderscoreParameters: true` respects this convention, producing initializer parameter names that omit the underscore:\n\n```swift\n@MemberwiseInit(.public, _deunderscoreParmeters: true)\npublic struct Review {\n  @Init(.public) private let _rating: Int\n\n  public var rating: String {\n    String(repeating: \"⭐️\", count: self._rating)\n  }\n}\n```\n\nThis yields:\n\n```swift\npublic init(\n  rating: Int  // 👈 Non-underscored parameter\n) {\n  self._rating = rating\n}\n```\n\nTo override the deunderscore behavior at the property level, use `@Init(label: String)`:\n\n```swift\n@MemberwiseInit(.public, _deunderscoreParameters: true)\npublic struct Review {\n  @Init(.public, label: \"_rating\") private let _rating: Int\n}\n```\n\nThis yields:\n\n```swift\npublic init(\n  _rating: Int  // 👈 Underscored parameter\n) {\n  self._rating = _rating\n}\n```\n\n### Experimental: Defaulting optionals to nil\n\nUse `@MemberwiseInit(_optionalsDefaultNil: Bool)` to explicitly control whether optional properties are defaulted to `nil` in the provided initializer:\n\n* Set `_optionalsDefaultNil: true` to default all optional properties to `nil`, trading off compile-time guidance.\n* Set `_optionalsDefaultNil: false` to ensure that MemberwiseInit never defaults optional properties to `nil`.\n\nThe default behavior of MemberwiseInit regarding optional properties aligns with Swift’s memberwise initializer:\n\n* For non-public initializers, `var` optional properties automatically default to `nil`.\n* For public initializers, MemberwiseInit follows Swift’s cautious approach to public APIs by requiring all parameters explicitly, including optionals, unless `_optionalsDefaultNil` is set to `true`.\n* `let` optional properties are never automatically defaulted to `nil`. Setting `_optionalsDefaultNil` to `true` is the only way to cause them to default to `nil`.\n\n\u003e **Note**\n\u003e Use [`@Init(default:)`](#default-values-even-for-let-properties) to generally specify default values — it’s a safer, more explicit alternative to `_optionalsDefaultNil`.\n\n#### Explanation\n\nWith `_optionalsDefaultNil`, you gain control over a default behavior of Swift’s memberwise init. And, it allows you to explicitly opt-in to your public initializer defaulting optional properties to `nil`.\n\nEasing instantiation is the primary purpose of `_optionalsDefaultNil`, and is especially useful when your types mirror a loosely structured external dependency, e.g. `Codable` structs that mirror HTTP APIs. However, `_optionalsDefaultNil` has a drawback: when properties change, the compiler won’t flag outdated instantiations, risking unintended `nil` assignments and potential runtime errors.\n\nIn Swift:\n\n* `var` property declarations that include an initial value naturally lead to default memberwise `init` parameter values in both Swift’s and MemberwiseInit’s initializers.\n* `let` properties assigned a value at declaration become immutable, so they can’t be leveraged to specify default `init` parameter values.\n\nFor instance, `var` property declarations can be initialized to `nil`:\n\n```swift\n@MemberwiseInit(.public)\npublic struct User {\n  public var name: String? = nil  // 👈\n}\n_ = User()  // 'name' defaults to 'nil'\n```\n\nYields:\n\n```swift\npublic init(\n  name: String? = nil  // 👈\n) {\n  self.name = name\n}\n```\n\nThis isn’t feasible for `let` properties:\n\n```swift\n@MemberwiseInit(.public)\npublic struct User {\n  public let name: String? = nil  // ✋ 'name' is 'nil' forever\n}\n```\n\nWhere appriopriate, `_optionalsDefaultNil` can be a convenient way to default optional properties to `nil` in the generated initializer:\n\n```swift\n@MemberwiseInit(.public, _optionalsDefaultNil: true)\npublic struct User: Codable {\n  public let id: Int\n  public let name: String?\n  public let email: String?\n  public let address: String?\n}\n```\n\nYields:\n\n```swift\npublic init(\n  id: Int,\n  name: String? = nil,\n  email: String? = nil,\n  address: String? = nil\n) {\n  self.id = id\n  self.name = name\n  self.email = email\n  self.address = address\n}\n```\n\n### Tuple destructuring in property declarations isn’t supported (yet)\n\nUsing tuple syntax in property declarations isn’t supported:\n\n```swift\n@MemberwiseInit\nstruct Point2D {\n  let (x, y): (Int, Int)\n//┬─────────────────────\n//╰─ 🛑 @MemberwiseInit does not support tuple destructuring for\n//     property declarations. Use multiple declartions instead.\n}\n```\n\n## Background\n\n[Swift’s automatically provided memberwise initializers][swifts-memberwise-init] deftly cut down on boilerplate for structs. Yet, they must always error on the side of caution to ensure no presumptions are made about the developer’s intent. While this conservative approach is essential for avoiding unintended behaviors, it too often leads back to using boilerplate initializers.\n\nSwift’s memberwise initializer can’t assume that a public type should be constructible from external modules, so it never provides an initializer having an access level greater than “internal.” To safely add a public initializer to a type requires an explicit developer intent. Traditionally, that means manually declaring an initializer, or using Xcode to generate a boilerplate initializer. Take this simple example:\n\n```swift\npublic struct Person {\n  public let name: String\n}\n```\n\nSwift transparently adds the following, familiar `init`:\n\n```swift\ninternal init(\n  name: String\n) {\n  self.name = name\n}\n```\n\nMemberwiseInit can provide the exact same `init`:\n\n```swift\n@MemberwiseInit  // 👈\npublic struct Person {\n  public let name: String\n}\n```\n\nUnlike Swift’s memberwise initializer, you can inspect MemberwiseInit’s initializer using Xcode by right clicking on `@MemberwiseInit` and the selecting “Expand Macro”.\n\n\u003e **Note**\n\u003e Introducing an explicit `init` suppresses the addition of Swift’s memberwise initializer. MemberwiseInit’s initializer is always added and can coexist with your other initializers, even for types directly conforming to `init`-specifying protocols like `Decodable` and `RawRepresentable`.[^1]\n\nIn contrast to Swift’s memberwise initializer, MemberwiseInit can provide an initializer at any access level, including public. You explicitly instruct MemberwiseInit to provide a public `init` by marking `Person` with `@MemberwiseInit(.public)`:\n\n```swift\n@MemberwiseInit(.public)  // 👈 `.public`\npublic struct Person {\n  public let name: String\n}\n```\n\nWith this adjustment, expanding the macro yields:\n\n```swift\npublic init(  // 🎉 `public`\n  name: String\n) {\n  self.name = name\n}\n```\n\nSuppose you then added a private member to `Person`:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  private var age: Int?  // 👈 `private`\n}\n```\n\nNow, rather than degrading to providing a private `init` as Swift’s memberwise initializer must, MemberwiseInit instead fails with a diagnostic:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  private var age: Int?\n//┬──────\n//╰─ 🛑 @MemberwiseInit(.public) would leak access to 'private' property\n//   ✏️ Add '@Init(.public)'\n//   ✏️ Replace 'private' access with 'public'\n//   ✏️ Add '@Init(.ignore)' and an initializer\n}\n```\n\n\u003e **Note**\n\u003e Both Swift’s and MemberwiseInit’s memberwise initializer are safe by default. Neither will provide an initializer that unintentionally leaks access to more restricted properties.\n\nTo publicly expose `age` via MemberwiseInit’s initializer, mark it with `@Init(.public)`:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  @Init(.public) private var age: Int?  // 👈 `@Init(.public)`\n}\n```\n\nand now MemberwiseInit provides a public `init` that exposes the private `age` property:\n\n```swift\npublic init(  // 👈 `public`\n  name: String,\n  age: Int?  // 👈 Exposed deliberately\n) {\n  self.name = name\n  self.age = age\n}\n```\n\nCompared to Swift’s memberwise initializer, MemberwiseInit’s approach has several advantages:\n\n1. **Clear Intent**: `@MemberwiseInit(.public)` is a declaration of the developer’s explicit intention, thereby avoiding any ambiguity about the desired access level for the initializer.\n2. **Safety**: By failing fast when expectations aren’t met, MemberwiseInit prevents unintended access level leaks that could compromise the encapsulation and safety of the code. That is, it is still safe by default.\n3. **Simpler**: MemberwiseInit’s reduced complexity makes it easier to use, as its behavior is more direct and predictable.\n4. **Learnable**: `@MemberwiseInit` can be applied naively, and most usage issues can be remedied in response to MemberwiseInit’s immediate feedback via diagnostic messages[^2].\n\nLet’s give `age` a default value:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  @Init(.public) private var age: Int? = nil  // 👈 Default value\n}\n```\n\nand now MemberwiseInit’s `init` parameter includes the default `age` value:\n\n```swift\npublic init(\n  name: String,\n  age: Int? = nil  // 👈 Default value\n) {\n  self.name = name\n  self.age = age\n}\n```\n\nSuppose we don’t want to expose `age` publicly via the `init`. As long as `age` is initialized in another way (e.g. declared with a default value), we can explicitly tell MemberwiseInit to ignore it using `@Init(.ignore)`:\n\n```swift\n@MemberwiseInit(.public)\npublic struct Person {\n  public let name: String\n  @Init(.ignore) private var age: Int? = nil  // 👈 `.ignore`\n}\n```\n\nNow MemberwiseInit ignores the private `age` property and provides a public `init`:\n\n```swift\npublic init(  // 👈 `public`, ignoring `age` property\n  name: String\n) {\n  self.name = name\n}\n```\n\n## License\n\nMemberwiseInit is available under the MIT license. See the [LICENSE][mit-license] file for more info.\n\n[^1]: Swift omits its memberwise initializer when any explicit `init` is present. You can do an [“extension dance”][extension-dance] to retain Swift’s memberwise `init`, but with imposed tradeoffs.\n[^2]: MemberwiseInit currently has some diagnostics accompanied by fix-its. However, it is actively working towards providing a more extensive and comprehensive set of fix-its. There are also usage errors presently left to the compiler checking the provided `init` that may be addressed directly in the future, e.g. rather than implicitly ignoring attributed properties marked with attributes like `@State`, MemberwiseInit may raise a diagnostic error and fix-its to add either `@Init`, `@Init(.ignore)`, or to assign a default value for the variable declaration.\n\n[swifts-memberwise-init]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/#Memberwise-Initializers-for-Structure-Types \"Swift.org: Memberwise Initializers for Structure Types\"\n[pointfreeco-website-memberwiseinit]: https://github.com/gohanlon/pointfreeco/compare/main...memberwise-init-macro \"Demo of Point-Free’s website using @MemberwiseInit\"\n[pointfreeco-isowords-memberwiseinit]: https://github.com/gohanlon/isowords/compare/main...memberwise-init-macro \"Demo of Point-Free’s Isowords using @MemberwiseInit\"\n[mit-license]: https://github.com/gohanlon/swift-memberwise-init-macro/blob/main/LICENSE \"MIT license\"\n[extension-dance]: https://gist.github.com/gohanlon/6aaeff970c955c9a39308c182c116f64\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgohanlon%2Fswift-memberwise-init-macro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgohanlon%2Fswift-memberwise-init-macro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgohanlon%2Fswift-memberwise-init-macro/lists"}