Is there markdown to document generic type parameters in Swift?

Viewed 339

There is a standard way to document function parameters in Swift. Like this:

/// - parameter num: blah blah blah
/// - parameter name: blah blah
func foo(num: Int, name: String) { ... }

Or this variation:

/// - parameters:
///    - num: blah blah blah
///    - name: blah blah
func foo(num: Int, name: String) { ... }

Is there a similar way to mark explanations of type parameters in generic types or functions? For example, something like the following:

/// - typeparam R: the row type
/// - typeparam C: the column type
struct MyView<R: Identifiable, C> { ... }
1 Answers

There isn't a way to explicitly document parameter types in Swift markup comments. For generics, depending on the circumstances, I notice that Xcode can sometimes resolve the types at the call site and fill them in, so you see the resolved type when you pull up Quick Help for it. I haven't pinned down all the rules about when it can do that and when it can't. I suspect it has to do with whether the source is available to it, or just a signature (such as from a library). In any case, I just notice that sometimes it resolves them in Quick Help, and sometimes it doesn't.

Although I'm not in the "don't comment code because it should be self-documenting" camp, I do believe the code should be as self-documenting as you can reasonably make it. Comments, including doc comments aren't compiled, and you don't get any kind of warning when they go out of date with respect to source code changes. On the other hand, naming can be hard so providing additional information can be important, plus not all relevant information about behavior can be reasonably put in the name, at least not without making names that are so long that they're worse than one character names. A comment can describe edge cases, things to watch out for, describe preconditions, etc... and doc comments in particular are good because you don't have to actually pull up the source for the thing you're calling to get that info.

That said, better type names would substantially give you the effect that you want, and since you're not restricted to one letter generic parameter types, you can do that even for generics. To use your example, instead of

struct MyView<R: Identifiable, C> { ... }

you could write

struct MyView<RowType: Identifiable, ColumnType> { ... }

And of course, your description of the parameters themselves will give information about the meaning.

For non-generic types, you can use typealias to do something similar:

struct User 
{
    typealias UserID = Int

    let id: UserID

    ...
}

Or take it a step further and gain some type safety by wrapping the primitive type in a struct. In the case of a user ID, do you really want to allow math to be done on it? Probably not. So to prevent that, you could do:

struct User 
{
    struct UserID: RawRepresentable
    {
        typealias RawValue = Int
        let rawValue: RawValue
    }

    let id: UserID

    ...
}

That way you get both a better self-documenting type name, and better type-safety. You can control what kinds of operations someone is allowed to do on an instance of UserID.

Related