Improve `inferType` documentation, KDocs, and test coverage
- Dominant language
- Kotlin
- Stars
- 1.1k
- Forks
- 83
- Avg merge
- 4d 12h
- Merged PRs (30d)
- 30
Description
# Improve `inferType` documentation, KDocs, and test coverage
## Context
`inferType` is useful when a column keeps a wider type than the values currently stored in it require.
Typical cases:
- after `filter`, when a column originally typed as `Any?`, `Comparable<*>`, or `Number?` now contains only values of a more specific type;
- after manual transformations such as `convert(...).with(Infer.None)`;
- after reading or constructing loosely typed data where columns initially have broad types;
- before schema-sensitive operations that benefit from more precise column types, such as `colsOf()`, `convertTo()`, typed accessors, schema checks, or serialization.
Important distinction: `inferType` does not parse or convert values. It only refines the column type based on already stored runtime values. For example, it may refine `Any?` to `Int?` if the values are already integers, but it will not convert `"123"` to `Int`.
Current website page:
https://kotlin.github.io/dataframe/infertype.html
Current source:
`core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/inferType.kt`
Current docs source:
`docs/StardustDocs/topics/inferType.md`
Existing tests:
`core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/inferType.kt`
## Problem
The current website page is too short and does not explain when `inferType` is useful in real DataFrame workflows.
The public API also has little or no KDoc, even though the behavior has important nuances:
- inference is based on existing runtime values;
- the result is the nearest common supertype of the values;
- inference is constrained by the current column type upper bound via `TypeSuggestion.InferWithUpperbound(type)`;
- `DataFrame.inferType()` applies to non-column-group columns at any depth;
- `inferType` is not parsing and should be distinguished from `parse` and `convert`.
The existing tests cover only a narrow subset of behavior.
## Acceptance Criteria
- The `inferType` website page explains why the operation exists and when users should consider it.
- The website clearly states that `inferType` does not parse or convert values.
- The website includes examples for whole-DataFrame inference, selected-column inference, and post-filter type refinement.
- Public non-deprecated `inferType` functions have KDocs.
- KDocs mention runtime-value-based inference, nearest common supertype behavior, and the current type upper bound.
- KDocs explain the default behavior of `DataFrame.inferType()`.
- Tests cover all non-deprecated public overloads.
- Tests cover nullable values, selected columns, whole-DataFrame inference, nested columns, and broad-to-specific type refinement.
- Tests include at least one scenario demonstrating that strings are not parsed into numbers by `inferType`.
## Website Recommendations
### 1. Add a “When to use it” section
Explain that `inferType` is useful when values have become more specific than the column type.
Suggested example:
```kotlin
val col by columnOf>("Alice", 1, 3.5)
val strings = col.filter { it is String }
strings.type() // Comparable<*>
strings.inferType().type() // String
```
### 2. Add a “What it does not do” section
Clarify that `inferType` does not parse or transform values.
Suggested example:
```kotlin
val col by columnOf("1", "2", "3")
col.inferType().type() // String?, not Int?
```
For converting strings to numbers, point users to `parse` or `convert`.
### 3. Document whole-DataFrame behavior
Explain that:
```kotlin
df.inferType()
```
infers types for non-column-group columns at any depth.
Mention that column groups themselves are not replaced by inferred value columns.
### 4. Document selected-column behavior
Show both name-based and selector-based usage:
```kotlin
df.inferType("value")
```
```kotlin
df.inferType {
colsOf()
}
```
### 5. Add a schema-sensitive workflow example
Show why type refinement is useful before operations that depend on column types:
```kotlin
val refined = df.inferType("value")
refined.select { colsOf() }
```
### 6. Link to related operations
Add a short “See also” section:
- `parse` for parsing string values into typed values
- `convert` for explicit conversion
- `convertTo()` for schema conversion
## KDoc Recommendations
Add KDocs to:
```kotlin
public fun AnyCol.inferType(): DataColumn<*>
public fun DataFrame.inferType(): DataFrame
public fun DataFrame.inferType(columns: ColumnsSelector): DataFrame
public fun DataFrame.inferType(vararg columns: String): DataFrame
```
Suggested KDoc topics:
- The operation refines column types based on already stored runtime values.
- It does not parse strings or convert values.
- The resulting type is the nearest common supertype of the current values.
- The inferred type is constrained by the current column type as an upper bound.
- `DataFrame.inferType()` applies to all non-column-group columns at any depth.
- Selected-column overloads preserve column names and positions.
- Typical use cases include post-filter narrowing, loosely typed input data, and recovery after transformations that intentionally disabled inference.
## Test Scenarios
### 1. `AnyCol.inferType()` narrows after filtering
Existing scenario can stay:
```kotlin
val col by columnOf>("Alice", 1, 3.5)
val filtered = col.filter { it is String }
filtered.inferType().type() shouldBe typeOf()
```
### 2. `DataFrame.inferType("column")` narrows a selected column
Create a DataFrame with two broad columns and verify that only the named column is refined.
### 3. `DataFrame.inferType { ... }` narrows selector-matched columns
Use a selector such as `colsOf()` or a name predicate and verify only selected columns are affected.
### 4. `DataFrame.inferType()` applies to non-column-group columns at any depth
Create a DataFrame with a nested column group containing broad typed value columns. Verify nested value columns are refined, while the column group structure is preserved.
### 5. Nullable values preserve nullability
Example expectation:
```kotlin
val col by columnOf(1, null, 2)
col.inferType().type() shouldBe typeOf()
```
### 6. Mixed values infer nearest common supertype
Example:
```kotlin
val col by columnOf(1, 2.0)
col.inferType().type()
```
Verify the expected common type according to the library’s type inference rules.
### 7. `inferType` does not parse strings
Example:
```kotlin
val col by columnOf("1", "2", "3")
col.inferType().type() shouldBe typeOf()
```
Also verify the values remain strings.
### 8. Inference respects current column type upper bound
Create a column with a declared broad-but-bounded type, then ensure inference does not produce a type outside the current upper bound.
### 9. Post-`convert(...).with(Infer.None)` refinement
Existing scenario can be kept and possibly expanded:
```kotlin
val converted = df.convert(col).with(Infer.None) {
B(it) as A
}
converted[col].type() shouldBe typeOf>()
converted.inferType(col)[col].type() shouldBe typeOf>()
```
Contributor guide
Research direction
Start with core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/inferType.kt and the existing test at core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/inferType.kt, then update docs/StardustDocs/topics/inferType.md. Run the existing inferType tests before expanding coverage for the listed overloads and scenarios. Done means the website and KDocs explain runtime-based inference and its limits, and the tests cover the stated behaviors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- documentation, testing-qa
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100