Widget ExtensionのWidgetファイルからProviderを切り離すとReference to invalid associated typeが出るエラーの対処法


iOSでウィジェットの実装をする時に、Widget Extensionを追加すると思うのですが、自動生成されるWidgetのファイル内に複数の構造体が含まれており、別ファイルに分割して整理しようと思いました。
その際にエラーが発生したのでその対処法を記載します。

## 環境
- Xcode 14.2
- iOS 16.2

## エラー再現方法

### Widget.swift

Widget Extensionを追加すると、`Widget Extensionの名前.swift`という名前で自動生成されるファイルです。

今回は例として`SimpleWidget.swift`とします。

```swift: SimpleWidget.swift
import WidgetKit
import SwiftUI

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date())
    }

    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date())
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        // Generate a timeline consisting of five entries an hour apart, starting from the current date.
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate)
            entries.append(entry)
        }

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
}

struct SimpleWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text(entry.date, style: .time)
    }
}

struct SimpleWidget: Widget {
    let kind: String = "SimpleWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            SimpleWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

struct SimpleWidget_Previews: PreviewProvider {
    static var previews: some View {
        SimpleWidgetEntryView(entry: SimpleEntry(date: Date()))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}
```

このファイルから`Provider`構造体を別ファイルに切り出します。

```swift: Provider.swift
import WidgetKit

struct Provider: TimelineProvider {
            
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date())
    }

    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date())
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        // Generate a timeline consisting of five entries an hour apart, starting from the current date.
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate)
            entries.append(entry)
        }

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}
```

新規作成したファイルのターゲットはデフォルトでアプリの方のターゲットになっている為、ファイルにターゲットをWidget Extensionに変更します。

![widget-target-change-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678954/af779fe4-dcd3-c713-682b-39bc03385921.png)

ファイルを切り出すと`getTimeLine`メソッドの引数内の`Timeline<Entry>`に対して、
`Reference to invalid associated type 'Entry' of type 'Provider'`
というエラーメッセージが表示されるようになってしまいます。

![entry-error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678954/8abca147-f4cd-35fa-ebce-352b890f6091.png)

## 対処法

### エラーの内容

参照している`Entry`は無効な`associated type`だよという内容になります。

#### typealiasを追加する

`typealias`を追加するとエラーが消えます。

```swift: Provider.swift

struct Provider: TimelineProvider {
    
    typealias Entry = SimpleEntry
               
// 省略

```

## おわりに

Widget.swiftが自動生成された時にはエラーは出ないのに、ファイルを切り出すとエラーが吐かれるのはどうしてなのだろうか、、🤔

一つのファイルの中に、下記5つが揃っている時には`associated type`参照エラーが出力されない。

- TimelineProvider
- TimelineEntry
- View
- Widget
- PreviewProvider

もし、わかる方いましたら優しく教えていただけると嬉しいです🙇

![lilossa-eyecatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678954/9d0469a6-b1b1-75d7-f4ba-7c5158019dab.png)