Skip to content
Go back

Property Getters vs Get Methods: When to Use Which

I kept seeing inconsistent patterns in codebases - sometimes obj.property, sometimes obj.getProperty(). After refactoring across TypeScript, Dart, and C# projects, here’s the simple rule I follow:

Property getters - computed values that feel like properties:

Get methods - operations that do work:

This pattern keeps my code predictable - if it looks like property access, it acts like one. If it has parentheses, I know it’s doing more work.

Examples

Configuration/State Checks:

// TypeScript - frontend config
class AppConfig {
  private _environment: string;
  
  get isDevelopment(): boolean {
    return this._environment === 'development';
  }
  
  get apiBaseUrl(): string {
    return this.isDevelopment 
      ? 'http://localhost:3000' 
      : 'https://api.production.com';
  }
}

// Usage
const config = new AppConfig();
console.log(config.apiBaseUrl);
if (config.isDevelopment) {  // No parentheses
  // Do something
}

Async Operations:

// Dart - platform channels
class AppConfig {
  Future<String> getBuildVersion() async {
    final info = await PackageInfo.fromPlatform();
    return '${info.version}+${info.buildNumber}';
  }
}

// Usage - must await
final version = await AppConfig.current.getBuildVersion();
setState(() => _buildVersion = version);

File/Network Operations:

// C# - file I/O
public class LogReader 
{
    public async Task<IEnumerable<FileInfo>> GetLogFilesAsync(string directory) 
    {
        return await Task.Run(() => 
            new DirectoryInfo(directory)
                .GetFiles("*.log")
                .OrderByDescending(f => f.LastWriteTime));
    }
}

// Usage
var logs = await reader.GetLogFilesAsync("/var/logs");

Share this post on:

Previous Post
Standardize Data at Write Time, Not Read Time
Next Post
My CloudFormation Template Organization