```ts
export function matchSetting(rules: Record<string, string>, name: string): string | null {
  if (typeof name !== "string" || name === "" || !/^[\w.]+$/.test(name)) {
    throw new Error("name must be a star-free non-empty string");
  }

  const parseSelector = (selector: string): [string, number] => {
    if (!/^\*|\*\.$|\.[^.]*\.*$/.test(selector)) {
      throw new Error(`Invalid selector: ${selector}`);
    }
    return selector === "*" ? ["*", -1] : [`.${name}`, name.length];
  };

  let bestMatch: [string, number] | null = null;

  for (const [selector, value] of Object.entries(rules)) {
    if (typeof value !== "string") {
      throw new Error(`Rule value must be a string`);
    }

    const [parsedSelector, selectorLength] = parseSelector(selector);

    if (parsedSelector === "*") {
      bestMatch = parsedSelector.length > 0 ? ["*", -1] : null;
    } else if (parsedSelector[0] === ".") && name.startsWith(parsedSelector.slice(1))) {
      const matchLength = name.slice(parsedSelector.length).indexOf(".", 1);
      const matchStart = parsedSelector.length + (matchLength !== -1 ? matchLength : name.length);
      bestMatch = [parsedSelector, matchStart];
    }
  }

  return bestMatch && bestMatch[0] === "*" ? null : rules[bestMatch![0]];
}
```